本文轉載自:衆成翻譯
譯者:iOSDevLog
連接:http://www.zcfy.cc/article/3825
原文:https://www.fullstackreact.com/30-days-of-react/day-20/react
使用Redux,咱們來談談咱們如何在咱們的應用中實際修改Redux狀態。redux
昨天, 咱們經歷了整合咱們的反應應用與Redux的困難部分。從如今起, 咱們將使用咱們的Redux設置來定義函數。異步
如今, 咱們的演示應用能顯示當前時間。但目前尚未任何方法能夠更新到新的時間。如今, 讓咱們修改這個。socket
回想一下, 咱們能在Redux中改變數據的惟一方法是經過一個動做建立者。昨天咱們建立了一個Redux的store, 但咱們尚未爲咱們的store創造一個更新的方法。函數
咱們 想要 的是咱們的用戶經過點擊按鈕來更新時間的能力。爲了添加此函數, 咱們須要執行如下幾個步驟:學習
建立一個 actionCreator 來 分發 咱們store的動做測試
調用一個元素的 actionCreator "onClick"fetch
處理歸約器的動做spa
咱們已經實現了第三個步驟, 因此咱們還有兩件事要作, 才能讓這個函數像咱們預期的那樣工做。翻譯
昨天, 咱們討論了什麼是動做, 但不是真正的爲何咱們使用這個東西叫 actionCreators 或他們是什麼。
做爲複習, 動做是一個_必須_ 包含type
值簡單的對象,。咱們建立了一個types.js
文件, 它保存在動做類型常量上, 所以咱們能夠將這些值用做type
屬性。
export const FETCH_NEW_TIME = 'FETCH_NEW_TIME';
做爲快速審閱, 咱們的動做能夠是具備type
鍵的任何對象值。咱們能夠與咱們的行動一塊兒發送數據 (一般, 咱們將把額外的數據做爲一個動做的 payload 有效載荷
來傳遞)。
{ type: types.FETCH_NEW_TIME, payload: new Date().toString() }
如今, 咱們須要在咱們的store
_分發_。咱們能夠這樣作的一個方法就是調用store.dispatch()
函數。
store.dispatch({ type: types.FETCH_NEW_TIME, payload: new Date().toString() })
然而, 這是至關糟糕的作法。咱們將使用一個函數來返回一個動做, 而不是直接發送該動做, 該函數將 建立 該動做 (所以名稱: actionCreator)。這爲咱們提供了一個更好的測試故事 (易於測試)、可重用性、文檔化和邏輯封裝。
讓咱們在一個名爲redux/actionCreators.js
的文件中建立咱們的第一個actionCreator
。咱們將導出所有責任是返回一個適當的動做的一個函數, 以分發咱們的store。
import * as types from './types'; export const fetchNewTime = () => ({ type: types.FETCH_NEW_TIME, payload: new Date().toString(), }) export const login = (user) => ({ type: types.LOGIN, payload: user }) export const logout = () => ({ type: types.LOGOUT, })
如今, 若是咱們調用這個函數, 什麼都不會發生 , 除了返回一個動做對象。咱們怎樣才能讓這個動做在store裏分發?
It gets called with the dispatch
function, so here we can bind the function to call dispatch()
on the store.回想一下, 咱們昨天使用了 connect()
函數導出從react-redux
?第一個參數稱爲mapStateToProps
, 它將狀態映射到一個屬性對象。connect()
函數接受第二個參數, 這使得咱們也能夠將函數映射到屬性。它被調用的dispatch()
函數, 因此在這裏咱們能夠 綁定 函數以便在store調用dispatch()
。
讓咱們來看看這個動做。在咱們的src/views/Home/Home.js
文件中, 讓咱們經過提供第二個函數來更新咱們的鏈接, 以使用咱們剛剛建立的 actionCreator。咱們將調用mapDispatchToProps
這個函數。
import { fetchNewTime } from '../../redux/actionCreators'; // ... const mapDispatchToProps = dispatch => ({ updateTime: () => dispatch(fetchNewTime()) }) // ... export default connect( mapStateToProps, mapDispatchToProps, )(Home);
如今, updateTime()
函數將做爲屬性傳遞, 並將調用dispatch()
當咱們開始行動。讓咱們更新咱們的 <Home />
組件, 以便用戶能夠按下一個按鈕來更新時間。
const Home = (props) => { return ( <div className="home"> <h1>Welcome home!</h1> <p>Current time: {props.currentTime}</p> <button onClick={props.updateTime}> Update time </button> </div> ); }
雖然這個例子並不使人興奮, 但它確實展現了Redux的特色。想象一下, 若是按鈕獲取新的鳴叫或咱們有一個socket驅動更新到咱們的Redux store。這個基本示例演示了Redux的完整功能。
如今, 咱們咱們的應用有一個單一的歸約器。這是目前的工做, 由於咱們只有少許的簡單數據和 (想必) 只有一我的在這個應用工做。試想一下, 在咱們的應用中爲_每一片數據_開發一個巨大的開關語句。
Ahhhhhhhhhhhhhh...
Redux去營救!Redux有一種方法, 咱們把咱們的Redux歸約器分紅多個歸約器, 每一個都只負責狀態樹的葉子。
咱們能夠從 redux
使用combineReducers()
導出, 以組成一個對象的歸約器函數。對於每一個觸發的動做, 將使用相應的動做調用每一個函數。讓咱們來看看這個動做。
假設咱們 (也許更現實一些) 想跟蹤當前用戶。讓咱們建立一個currentUser
Redux模塊..。您猜到了: src/redux/currentUser.js`:
touch src/redux/currentUser.js
咱們將導出咱們從currentTime
模塊導出的相同的四個值...... 固然, 這一次是針對 currentUser 的。咱們在這裏添加了一個基本的結構來處理當前用戶:
import * as types from './types' export const initialState = { user: {}, loggedIn: false } export const reducer = (state = initialState, action) => { switch (action.type) { case types.LOGIN: return { ...state, user: action.payload, loggedIn: true}; case types.LOGOUT: return { ...state, user: {}, loggedIn: false}; default: return state; } }
讓咱們更新咱們的configureStore()
函數來考慮這些分支, 使用combineReducers
將兩個分支分開
import { createStore, combineReducers } from 'redux'; import { rootReducer, initialState } from './reducers' import { reducer, initialState as userInitialState } from './currentUser' export const configureStore = () => { const store = createStore( combineReducers({ time: rootReducer, user: reducer }), // root reducer { time: initialState, user: userInitialState }, // our initialState ); return store; } export default configureStore;
如今, 咱們能夠建立login()
和logout()
動做創造者在咱們的store發送動做。
export const login = (user) => ({ type: types.LOGIN, payload: user }) // ... export const logout = () => ({ type: types.LOGOUT, })
如今, 咱們能夠使用 actionCreators 像updateTime()
動做創造者同樣調用login
和 logout
。
哦!這是Redux代碼的又一個沉重的一天。今天, 咱們完成了數據更新和在全局Redux狀態中存儲數據之間的循環。此外, 咱們還學習瞭如何擴展Redux以使用多個歸約器和動做以及多個鏈接的組件。
可是, 咱們尚未對站外數據進行異步調用。明天咱們將進入如何使用中間件與Redux, 這將使咱們可以處理從咱們的應用中獲取遠程數據, 仍然使用Redux的能力來保存咱們的數據。
今天的工做很好, 明天見!