此次要總結的是對 store 和 reducer 的拓展,好比發送異步的 action 操做,還有一個就是對多個 reducer 的管理。css
首先來總結一下 react-redux 的使用:react
<!-- reducer -->
function handleUser(state = [], action) {
switch (action.type) {
case 'ADD_USER':
state.push(action.user)
return [...state];
case 'DELETE_USER':
state.splice(action.payload, 1);
return [...state];
default:
return state
}
}
export { handleUser };
<!-- store -->
import { createStore } from 'redux';
import { handleUser } from '../Reducer/handleUser';
const store = createStore(handleUser);
export { store };
複製代碼
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { store } from './Redux/Store/store';
import * as serviceWorker from './serviceWorker';
import './assets/_reset.scss';
// 引入頁面
import { UserContainer } from './Pages/UserContainer';
ReactDOM.render(
<Provider store={ store }>
<UserContainer />
</Provider>,
document.getElementById('root')
)
複製代碼
<!-- action -->
const addUser = (user) => ({
type: 'ADD_USER',
user: user
})
const deleteUser = (index) => ({
type: 'DELETE_USER',
index: index
})
export { addUser, deleteUser };
<!-- pages -->
import { addUser, deleteUser } from '../Redux/Action/addUserData';
const mapStateToProps = (state) => {
return {
userList: userList
}
}
const mapDispatchToProps = (dispatch) => {
return {
addUserData: (user) => {
return dispatch(addUser(user))
},
deleteUserData: (index) => {
return dispatch(deleteUser(index))
}
}
}
UserContainer = connect(mapStateToProps, mapDispatchToProps)(UserContainer);
複製代碼
以上就是 react-redux 的使用,下面繼續拓展其餘使用方式。redux
combineReducers 是 redux 提供的一個方法,調用這個方法而且傳入多個 reducer ,而後對這些 reducer 進行管理:promise
import { combineReducers } from 'redux';
import { handleUser } from './handleUser';
<!-- 寫法一 -->
const chatReducer = combineReducers({
userList: handleUser,
<!-- ...這裏能夠寫更多 reducer -->
})
<!-- 寫法二 -->
const chatReducer = combineReducers({
handleUser,
<!-- ...這裏能夠寫更多 reducer -->
})
export { chatReducer };
複製代碼
上面的 combineReducers 傳入的對象有兩個寫法,可是每一個寫法最終呈現的名字必需要與 state 同樣:bash
const mapStateToProps = (state) => {
return {
<!-- 這時 state 返回的是一個對象,裏面返回各個 reducer 返回的 state -->
userList: state.userList
}
}
複製代碼
還有一點就是 store 設置默認值的問題。app
<!-- 使用 combineReducers 以前-->
const store = createStore(
handleUser,
state
)
<!-- 使用 combineReducers 以後-->
const store = createStore(
chatReducer,
{ userList: state } // 這裏參數必須是個對象,並且對象裏面的鍵要和 combineReducers 設置的相同。
)
複製代碼
store 能夠接受三個參數,第一個參數是 reducer ,第二個參數表明狀態默認值,用於覆蓋 reducer 的默認狀態。dom
目前的 store 並不具有處理異步 action 的能力,咱們可使用 中間件 來實現這個操做。異步
applyMiddleware 是 store 的第三個參數,它是一個函數,用來拓展 store ,這個方法來源於 redux 。ide
import { createLogger } from 'redux-logger';
const logger = createLogger();
const store = createStore( chatReducer, { userList: defaultUserList }, applyMiddleware(logger));
複製代碼
logger 能夠在發送 action 時打印狀態的變化以及 action 的信息:函數
import thunk from 'redux-thunk';
import { createLogger } from 'redux-logger';
const logger = createLogger();
const store = createStore(
chatReducer,
{ userList: defaultUserList },
applyMiddleware(thunk, logger)
);
複製代碼
正常狀況下,dispatch 傳遞的參數只能是對象:
addUserData: (user) => {
return dispatch({
type: 'ADD_USER',
payload: user
})
}
複製代碼
使用 redux-thunk 讓 dispatch 接受一個函數,讓他可以進行異步操做:
addUserData: (user) => {
return dispatch((dispatch, getState)=> {
setTimeout(()=> {
dispatch(addUser(user))
}, 2000)
})
}
複製代碼
傳遞一個函數以後,這個函數能夠接受兩個參數,一個是 dispatch ,另外一個是 getState ,而後在裏面進行異步操做,我這裏設置了 2秒 而後添加了一個用戶,點擊以後,過了 2秒 個人用戶纔會被添加進去,而頁面也是等到 2秒 後從新渲染。
這種異步思路就是使用 Action Creator 返回一個函數,而後使用 redux-thunk 讓 dispatch 可以接受一個函數做爲參數。
import thunk from 'redux-thunk';
import { createLogger } from 'redux-logger';
import promiseMiddleware from 'redux-promise';
const logger = createLogger();
const store = createStore(
chatReducer,
{ userList: defaultUserList },
applyMiddleware(thunk, promiseMiddleware, logger) // 按照嚴格的循序
);
複製代碼
上一種方法是使用 Action Creator 返回函數來操做異步,使用 redux-promise 可讓它返回一個 promise 對象,可使用 then 來實現後面的操做。
deleteUserData: (index) => {
return dispatch(new Promise((resolve, reject)=> {
setTimeout(()=> {
dispatch(deleteUser(index))
}, 2000)
}))
}
複製代碼
使用 redux-promise 讓它可以返回一個 使用 promise ,接着咱們調用 使用 deleteUserData 函數時就能夠執行 then 的操做。
以上三個中間件都是對 store 的拓展,使用 applyMiddleware 而且分別傳入三個 中間件 ,傳入時必需要遵循順序,不然會出問題:
applyMiddleware(thunk, promiseMiddleware, logger)
複製代碼