2017-04-20 24 views
3

在項目中使用ARc(Atomic React)(這非常棒,我認爲對於最終將要實現的內容,一個企業級的產品),但它只是未來的證明,如果我不把它們拼錯在一起,我目前無法理解我的應用中如何/何時/何地/爲何使用選擇器。在react/redux/saga /選擇器設置中努力工作

看過這個:How is state passed to selectors in a react-redux app?這很棒,但我認爲還需要看幾個實例才能真正得到它。

我試圖解決的當前問題是獲取一個user對象(可在整個應用程序範圍內訪問),並且通過該數據爲用戶可修改的帳戶設置頁創建一個友好的界面狀態他們自己的名字,電子郵件等。我不想只使用user商店,因爲他們不希望他們改變任何東西,直到他們實際上提交了,但是確實想用redux維護表單狀態。

我在我的用戶加載哪個都好(可以通過上,我想不同的容器道具訪問): 操作:

export const USER_GET_REQUEST = 'USER_GET_REQUEST' 
export const USER_GET_REQUEST_SUCCESS = 'USER_GET_REQUEST_SUCCESS' 
export const USER_GET_REQUEST_FAILURE = 'USER_GET_REQUEST_FAILURE' 

export const getUserRequest = (params, resolve, reject) => ({ 
    type: USER_GET_REQUEST, 
    params, 
    resolve, 
    reject, 
}) 

export const getUserRequestSuccess = user => ({ 
    type: USER_GET_REQUEST_SUCCESS, 
    user, 
}) 

export const getUserRequestFailure = error => ({ 
    type: USER_GET_REQUEST_FAILURE, 
    error, 
}) 

傳奇故事:

import { take, put, call, fork } from 'redux-saga/effects' 
import api from 'services/api' 
import * as actions from './actions' 

export function* readGetUser() { 
    try { 
    const data = yield call(api.get, '/user') 
    yield put(actions.getUserRequestSuccess(data)) 
    } catch (e) { 
    yield put(actions.getUserRequestFailure(e)) 
    } 
} 

export function* watchUserGetRequest() { 
    while (true) { 
    const { params } = yield take(actions.USER_GET_REQUEST) 
    yield call(readGetUser, params) 
    } 
} 

export default function*() { 
    yield fork(watchUserGetRequest) 
} 

減速機:

import { initialState } from './selectors' 
import { USER_LOGIN_SUCCESS, USER_GET_REQUEST_SUCCESS } from './actions' 

export default (state = initialState, action) => { 
    switch (action.type) { 
    case USER_LOGIN_SUCCESS: 
     return state 
    case USER_GET_REQUEST_SUCCESS: 
     return { 
     ...state, 
     user: action.user, 
     } 
    default: 
     return state 
    } 
} 

選擇器(我的廢話代碼評論,單線作品儘可能使user實際上有用戶數據,但在哪裏計算數據轉到/它是如何到達那裏的。

export const initialState = { 
    user: {}, 
} 

export const getUser = (state = initialState) => state.user || initialState.user 

// export const getUser = (state = initialState) => { 
// if (state.user) { 
//  return Object.assign({}, state, { 
//  formData: { 
//   firstName: state.user.firstName, 
//   lastName: state.user.lastName, 
//   email: state.user.email, 
//   phone: state.user.phone, 
//  }, 
//  }) 
// } 
// 
// return initialState.user 
// } 

代碼幫助是驚人的,清晰的解釋讓我堅定不移的感情和感激+在我的自傳中提到。

+0

您能澄清一下問題嗎?它主要歸結爲「我何時使用選擇器功能」?我知道,Eesh, – markerikson

+0

。我寫了這個問題,並重寫了這個問題10次,試圖從根本上解決混亂問題。是的,何時何地使用選擇器函數,以及如何在這個特定的實例中分離出一些表單數據? – megkadams

+0

你需要閱讀這個問題的每一個答案 - http://stackoverflow.com/q/35411423/1477051 –

回答

3

選擇器功能可以並且應該用於任何想要從商店中提取特定數據片段的地方。把它們想象成「查詢你的狀態樹」,就像SQL查詢到數據庫中一樣。

它們在您的mapStateToProps函數中最常用於提取組件需要的數據,但也適用於需要基於存儲內容運行條件邏輯的地方(如thunk動作創建者或sagas)。如果你願意,你甚至可以在減速器中使用它們。

選擇器通常使用reselect庫創建,它記錄輸入。這意味着最終提供的「輸出」功能只有在輸入實際發生變化時纔會運行。一個簡單的例子可能是:

import {createSelector} from "reselect"; 

const selectUser = state => state.user; 

const selectUserFirstName = createSelector(
    selectUser, 
    user => user.firstName 
); 

const selectUserLastName = createSelector(
    selectUser, 
    user => user.lastName 
); 

const selectUserFullName = createSelector(
    [selectUserFirstName, selectUserLastName], 
    (firstName, lastName) => firstName + " " + lastName 
); 

在這個例子中,「名字+姓氏」選擇將只有兩個輸入一個實際上已經改變了運行。否則,它將返回以前的緩存結果值。然後,這可能被用作:

const mapState = (state) => { 
    const userFullName = selectUserFullName(state); 

    return {userFullName}; 
} 

有關選擇器的詳細信息,請參閱我的React/Redux links listRedux Techniques#Selectors and Normalization部分。我也使用我的Practical Redux tutorial series中的選擇器。 (作爲相關說明,您可能需要閱讀Practical Redux Part 8: Form Draft Data Management或我的鏈接列表中的React and Forms部分的一些文章。)

+0

因此,欣賞筆記,並興奮地閱讀。不知道爲什麼ARc(https://github.com/diegohaz/arc/tree/redux)沒有使用重新選擇框 - 是否有任何理由可以考慮不包括我應該留意的圖書館? – megkadams

+0

假設這只是他們選擇包含在樣板中的庫的問題。鑑於它們包含了重新編排的傳奇,我只是有點驚訝他們沒有包括重新選擇。但是,絕對沒有理由不包括它。這是一個小巧的輕量級庫,並且與Redux一起廣泛使用。此外,請隨時通過https://www.reactiflux.com的Reactiflux聊天頻道下載並提出更多問題。我在美國時間晚上(@acemarke)閒逛,還有很多其他人也樂於回答問題。 – markerikson

+0

將馬上退房!謝謝! :) – megkadams