1. Redux 核心
目标:搞懂 Redux 本身是怎么回事;以及 Redux 如何使用
1.1 什么是 Redux
- Redux 是一个状态容器【即保存了一些数据的 JavaScript 对象,这些数据跟页面中 DOM 元素的状态是对应关系】
状态容器的好处:不需要查找页面的 DOM 元素去操作它,可以直接操作 DOM 元素对应的状态对象就好了
问:仅仅操作 DOM 元素对应的状态对象,是如何将状态更新到页面中的?
答:DOM 的操作可以交给框架去操作
- Redux 提供可预测化的状态管理
Redux 提供了一种科学的状态管理方式,通过这种方式,当状态发生变化时,该就变得可预测。当状态出现问题的时候,我们很容易定位到出问题的地方。
1.2 Redux 核心概念以及 Redux 工作流程
Redux 中有 4 个核心概念:
- Store:存储状态的容器,是一个 JavaScript 对象。Redux 要求我们把所有的状态都存储到 Store 中
- View:视图,HTML 页面
- Actions:Javascript对象,对象中要有一个固定的属性
type
,type是一个字符串。它的作用是用来描述要对 Store 状态进行什么样的操作 - Reducer:函数,用来向 Store 中存储状态,以及更新 Store 中的状态。也就是说 Reducer 中返回什么,store 就存什么
Redux 工作流程
Redux 的 4 个核心概念组合起来,要怎么使用?
- 视图(View) 是不能直接操作 Store 状态的,只能先通过触发(
dispatch
) Actions 描述当前需要对 Store 进行怎样的操作 - 而 Actions 会被 Reducer 接收到,在其内部会根据 Actions 的 type 的属性值进行相应操作,当状态处理完成之后返回最新处理好的状态,然后更新到 Store 中。
- Store 中的状态更新完成之后,同步(
subscribe
)给视图
1.3 Redux 核心 API
- createStore:用于创建 store 状态的方法,它的第一个参数是 Reducer,第二个参数是 Reducer 的默认参数(默认 state 状态对象)
- Reducer:是一个函数,它接受两个参数,一个是
state
,一个是action
- Reducer:是一个函数,它接受两个参数,一个是
- getState():获取 store 中存储的状态
- subscribe():订阅状态
- dispatch():触发 action
1.4 Redux 计数器
// 3. 默认状态
var initialState = { count: 0 }
// 2. 创建 Reducer 函数,该函数其实就是 createStore 的第一个参数
var reducer = function (state = initialState, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 }
case 'decrement':
return { count: state.count - 1 }
default: state
}
}
// 1. 创建 Store 对象
var store = Redux.createStore(reducer)
// 4. 定义 action
var increment = { type: 'increment' }
var decrement = { type: 'decrement' }
// 5. 获取按钮,添加点击事件
document.getElementById('plus').onclick = function () {
// 6. 触发 action
store.dispatch(increment)
}
document.getElementById('minus').onclick = function () {
// 6. 触发 action
store.dispatch(decrement)
}
// 7. 订阅 store
store.subscribe(() => {
// 8. 更新视图
document.getElementById('count').innerText = store.getState().count
})
2. React + Redux
目标:React 中如何使用 Redux;解决 React 中组件与组件之间共享数据的问题
2.1 React 中不使用 Redux 时的问题
- React 组件之间通信的数据流是单向的,上层组件可以通过 props 属性向下层组件传递数据,而下层属性不能向上层组件传递数据。
- 如果需要更改数据,下层组件只能通过调用上层组件传递的修改数据的方法。
- 当项目越来越大的时候,组件之间传递数据、传递修改数据的方法就会变得越来越困难
2.2 React 中使用 Redux 的好处
- Redux 应用程序要求我们要把所有的状态都存储到 store 状态容器当中,
- 由于 Store 是独立于组件之外的,使得数据也独立于组件之外,如果有哪个组件需要使用到该数据的,可以直接从 store 中去获取即可。
- 从而解决了组件与组件之间数据传递困难的问题
2.3 React 中使用 Redux
Redux 真正工作流程:
- 组件通过dispatch方法触发Action
- Store接收Action并将Action分发给Reducer
- Reducer根据Action类型对状态进行更改并将更改后的状态返回给Store
- 组件订阅了Store 中的状态,Store中的状态更新会同步到组件。
2.4 React + redux 的使用
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore } from 'redux';
const initialState = { count: 0 }
function reducer(state = initialState, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 }
case 'decrement':
return { count: state.count - 1 }
default: return state
}
}
const store = createStore(reducer)
const increment = { type: 'increment' }
const decrement = { type: 'decrement' }
function Counter() {
return <div>
<button onClick={() => store.dispatch(decrement)}>-</button>
<span>{store.getState().count}</span>
<button onClick={() => store.dispatch(increment)}>+</button>
</div>
}
store.subscribe(() => {
ReactDOM.render(
<React.StrictMode>
<Counter />
</React.StrictMode>,
document.getElementById('root')
);
})
ReactDOM.render(
<React.StrictMode>
<Counter />
</React.StrictMode>,
document.getElementById('root')
);
至此 react + redux 的基础代码已经实现了,但是存在一些问题:
- 代码写的太生硬了,就比如 render 写了两遍;
- 而且组件应该分离到单独组件中去的。但是如果分离到单独组件又拿不到 store 了。
怎么解决?如何将 React 和 redux 完美结合使用?
2.5 React + redux + react-redux
分离时遇到的问题和解决方案
- 当我们尝试将Counter抽离出去放在Component文件夹时,发现我们在这里就无法拿到Store了。——把Store变为全局可取的
下载 Redux:npm i redux react-redux
- react-redux
- Provider:组件,它可以把 store 放到一个全局的地方。Provider 组件要包裹项目中所有的组件,也就是要作为最外层的组件使用
- connect:方法,
- 内部会订阅 store,当 store 中的状态变化时会重新渲染组件
- 通过 connect 方法拿到 store 的状态,将状态映射到组件的 Props 属性中:connect 方法的第一个参数
- 通过 connect 方法拿到 dispatch 方法:connect 方法的第二个参数
Provider 的使用
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import Counter from './components/counter';
const initialState = { count: 0 }
function reducer(state = initialState, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 }
case 'decrement':
return { count: state.count - 1 }
default: return state
}
}
const store = createStore(reducer)
const increment = { type: 'increment' }
const decrement = { type: 'decrement' }
ReactDOM.render(
<Provider store={store}>
<Counter />
</Provider>,
document.getElementById('root')
);
connect 方法的使用
import React from 'react';
import { connect } from 'react-redux';
function Counter(props) {
return <div>
<button onClick={() => props.dispatch({ type: 'decrement' })}>-</button>
<span>{props.count}</span>
<button onClick={() => props.dispatch({ type: 'increment' })}>+</button>
</div>
}
const mapStateToProps = (state) => ({
count: state.count
})
// connect 方法接收一个函数,这个函数的参数是 store 中的 state,返回一个对象,这个对象会被映射到组件的 props 属性中
// connect 方法返回一个函数,该函数需要接收一个组件(需要使用到 store 状态的组件)
export default connect(mapStateToProps)(Counter)
优化1
在 Counter 组件中写了 onClick 代码太长,影响了组件代码的可读性,我们期望在点击按钮的时候,通过一个函数来触发 action
比如:<button onClick={decrement}>-</button>
要如何实现这个需求呢?
此时我们就需要用到 connect 方法的第二个参数,它也是函数,该函数可以拿到 store 的 dispatch 方法
import React from 'react';
import { connect } from 'react-redux';
function Counter({ count, decrement, increment}) {
return <div>
<button onClick={decrement}>-</button>
<span>{count}</span>
<button onClick={increment}>+</button>
</div>
}
const mapStateToProps = (state) => ({
count: state.count
})
const mapDispatchToProps = (dispatch) => ({
decrement() {
return dispatch({ type: 'decrement' })
},
increment() {
return dispatch({ type: 'increment' })
},
})
// connect 方法第一个参数接收一个函数,这个函数的参数是 store 中的 state,返回一个对象,这个对象会被映射到组件的 props 属性中
// connect 方法第二个参数接收一个函数,这个函数的参数是 store 中的 dispatch 方法,返回一个对象,这个对象会被映射到组件的 props 属性中
// connect 方法返回一个函数,该函数需要接收一个组件(需要使用到 store 状态的组件)
export default connect(mapStateToProps, mapDispatchToProps)(Counter)
优化2
通过观察 Counter 组件的代码发现,mapDispatchToProps 函数里面还是有重复的代码,我们接着优化它
这里通过 redux 提供的一个方法 —— bindActionCreators
bindActionCreators
方法用于创建 dispatch 的 actions,它接收两个参数,第一个参数是 actions 对象,第二个参数是 dispatch。返回一个生成好的 dispatch 对象
新建一个文件:src/store/actions/counter.actions.js
export const increment = () => ({ type: 'increment' })
export const decrement = () => ({ type: 'decrement' })
在 Counter 组件中导入 counter actions 并传入给 bindActionCreators
方法
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as counterActions from '../store/actions/counter.actions';
...
const mapDispatchToProps = (dispatch) => bindActionCreators(counterActions, dispatch)
// connect 方法接收一个函数,这个函数的参数是 store 中的 state,返回一个对象,这个对象会被映射到组件的 props 属性中
// connect 方法返回一个函数,该函数需要接收一个组件(需要使用到 store 状态的组件)
export default connect(mapStateToProps, mapDispatchToProps)(Counter)
2.6 为 action 传递参数
组件中点击时,给 action 传参
function Counter({ count, decrement, increment }) {
return (
<div>
<button onClick={() => decrement(5)}>-</button>
<span>{count}</span>
<button onClick={() => increment(5)}>+</button>
</div>
);
}
action 中接收
payload
参数,并传递给 reducerexport const increment = (payload) => ({ type: INCREMENT, payload });
export const decrement = (payload) => ({ type: DECREMENT, payload });
reducer 接收到 action 形参,并使用 payload
const reducer = (state = initialState, action) => {
switch (action.type) {
case INCREMENT:
return { count: state.count + action.payload };
case DECREMENT:
return { count: state.count - action.payload };
default:
return state;
}
};
2.7 拆分合并 reducer
在一个真实项目中,可能会触发多个 reducer,如果将所有 reducer 都放在同一个 reducer 文件中的话,就会变得臃肿,不可维护。所以我们应当将不同模块的 reducer 拆分出来,然后再组合起来。
拆分
modal.reducer.js
import { HIDE_MODAL, SHOW_MODAL } from '../const/modal.const';
const initialState = { show: false };
const reducer = (state = initialState, action) => {
switch (action.type) {
case SHOW_MODAL:
return { ...state, show: true };
case HIDE_MODAL:
return { ...state, show: false };
default:
return state;
}
};
export default reducer;
count.reducer.js
import { DECREMENT, INCREMENT } from '../const/counter.const';
const initialState = { count: 0 };
const reducer = (state = initialState, action) => {
switch (action.type) {
case INCREMENT:
return { ...state, count: state.count + action.payload };
case DECREMENT:
return { ...state, count: state.count - action.payload };
default:
return state;
}
};
export default reducer;
每一个模块的 reducer 的结构都是相同的
合并
使用 redux 提供的 combineReducers
函数,将多个小的 reducer 组合在一起
root.reducer.js
import { combineReducers } from 'redux';
import counterReducer from './counter.reducer';
import modalReducer from './modal.reducer';
// { counter: { count: 0 }, modal: { show: false } }
export default combineReducers({
counter: counterReducer,
modal: modalReducer
});
组件中使用
const mapStateToProps = (state) => ({
showState: state.modal.show
});
const mapStateToProps = (state) => ({
count: state.counter.count
});
3. Redux 中间件
目标:搞懂什么是 Redux 中间件,以及工作中常用的 Redux 中间件的使用
3.1 什么是中间件
中间件本质上是一个函数,Redux 允许我们使用中间件的方式扩展和增强 React 应用程序,而这个增强则体现在对 action 的处理能力上。
前面在处理 action 的时候,action 是直接交给 reducer 去处理的;而如果加上了中间件的话, action 会优先被中间件处理,然后再被 reducer 处理
3.2 加上中间件之后 React 的工作流程:
3.3 开发 Redux 中间件
中间件的模板:
export default store => next => action => {
console.log(store);
console.log(action);
next(action)
}
由模板可以看出:
- Redux 中间件是一个函数(柯里化函数),这个函数要求返回一个函数,在返回的函数中,要求再返回一个函数,而在最里层的函数中可以执行自己的业务逻辑
- 最外层的函数提供一个参数
store
,可以通过store.getState()
方法获取当前这个 store 的状态,通过store.dispatch()
方法去触发另一个 action - 最里层的函数也有一个形参
action
,这个 action 则是组件触发的那个 action,可以通过判断action.type
来决定是否对这个 action 进行处理,或者进行什么样的处理 - 中间层的函数也有一个参数
next
,它是一个函数,当最里层的中间件逻辑执行完之后,需要调用 next,将当前 action 传递给 reducer 或者说传递给下一个中间件。next(action);
3.4 注册中间件
中间件只有被注册到 Store 之后才会在 Redux 的工作流程中生效
import { applyMiddleware, createStore } from 'redux';
import logger from './middleware/logger';
import reducer from './reducers/root.reducer';
const store = createStore(
reducer,
/* 这里本来是 reducer 的默认参数,但是它是可选的, 所以可以将 applyMiddleware 放在第二个参数上 */
applyMiddleware(logger)
);
export default store;
Redux 中提供了 applyMiddleware
函数,它可以作为 createStore
函数的第三个参数,但由于 createStore 的第二个参数是可选的,所以可以将它放在第二个参数;applyMiddleware
接收中间件作为参数
多个中间件如何应用?
middleWare/test.js
export default store => next => action => {
console.log('test 中间件被执行了')
// 一定要调用next方法,这样才能将action传递给下一个中间件或者reducer
next(action)
}
import { applyMiddleware, createStore } from 'redux';
import logger from './middleware/logger';
import test from './middleware/test';
import reducer from './reducers/root.reducer';
const store = createStore(
reducer,
applyMiddleware(logger,test)
);
export default store;
中间件的执行顺序:取决于传入 注册的顺序,也**applyMiddleware**
函数的参数顺序
假设我们要延迟加或者减的操作,应该如何去实现呢?
实现思路:
- 使用中间件实现
- 通过中间件的最后一个参数action的type判断是否为增减操作,如果是,就延迟传递action给reducer
(也就是延迟执行next(action)方法)
middleWare/thunk.js
export default store => next => action => {
const {type} = action;
if(['increment','decrement'].includes(type)){
setTimeout(()=>{
next(action)
},2000)
}else{
next(action)
}
}
注册 thunk
import { applyMiddleware, createStore } from 'redux';
import logger from './middleware/logger';
import test from './middleware/test';
import thunk from './middleware/thunk';
import reducer from './reducers/root.reducer';
const store = createStore(
reducer,
applyMiddleware(logger,test,thunk)
);
export default store;
到此延迟加减的功能已经实现了,但是这种代码书写方式并不好,不灵活。
比如说我们要在弹框中加入异步操作,在显示和隐藏这两个按钮加入延时操作,是不是又得写一个相似的中间件了。如何写得通用一些?
3.5 中间件添加异步操作
- 当前中间件不关心执行的是什么样的异步操作,只关心你执行的是不是一个异步操作
- 如果你执行的是异步操作,在触发 action 的时候,传递一个函数;如果是同步操作,就传递一个 action 对象即可
- 异步操作代码要写在 传递过来的函数中
- 当前中间件会调用你传递进来的函数,并将 dispatch 方法传递过去
- 当你的异步函数执行完成之后,去调用 dispatch 方法,去触发另一个 action,并向这个 action 传递参数,再传递给 reducer。这样就可以把异步结果传递给 reducer 中了
thunk.js
const thunk = ({ dispatch }) => (next) => (action) => {
if (typeof action === 'function') {
return action(dispatch);
}
next(action);
};
export default thunk;
counter.action.js
import { DECREMENT, INCREMENT } from '../const/counter.const';
export const increment = (payload) => ({ type: INCREMENT, payload });
export const decrement = (payload) => ({ type: DECREMENT, payload });
export const increment_async = (payload) => (dispatch) => {
setTimeout(() => {
dispatch(increment(payload));
}, 2000);
};
- 当我们想要执行异步操作的时候,我们在actionCreator这个地方不返回一个对象 ,而是返回一个函数
- 我们在返回的这个函数中执行异步操作,通过调用dispatch方法触发一个其他的action
- 通过参数将异步操作的结果传递给其他的action, 通过其他的action传递数据给reducer, reducer再处理保存这个数据。
counter.js
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as counterActions from '../store/actions/counter.actions';
function Counter({ count, decrement, increment, increment_async }) {
return (
<div>
<button onClick={() => decrement(5)}>-</button>
<span>{count}</span>
<button onClick={() => increment_async(5)}>+</button>
</div>
);
}
const mapStateToProps = (state) => ({
count: state.counter.count
});
const mapDispatchToProps = (dispatch) =>
bindActionCreators(counterActions, dispatch);
// connect 方法接收一个函数,这个函数的参数是 store 中的 state,返回一个对象,这个对象会被映射到组件的 props 属性中
// connect 方法返回一个函数,该函数需要接收一个组件(需要使用到 store 状态的组件)
export default connect(mapStateToProps, mapDispatchToProps)(Counter);
4. Redux 常用中间件
4.1 redux-thunk
redux-thunk 中间件的作用和用法与 thunk 中间件是一样的,它允许我们在使用 redux 的过程中加入异步操作,而 thunk 就是仿照 redux-thunk 来做的
- 安装:
npm install redux-thunk
- 引入:
import thunk from 'redux-thunk'
- 注册:
createStore(reducer, applyMiddleware(thunk))
4.2 redux-saga
redux-saga 与 redux-thunk 作用是一样的,都是允许我们在 redux 工作流程中加入异步代码。但是 redux-saga 更加强大,它允许我们把异步操作从 Action Creator 中抽离出来,放在一个单独的文件中
- 安装:
npm install redux-saga
- 引入:
import createSagaMiddleware from 'redux-saga'; const sagaMiddleware = createSagaMiddleware();
- 注册:
createStore(reducer, applyMiddleware(sagaMiddleware))
import { applyMiddleware, createStore } from 'redux';
import reducer from './reducers/root.reducer';
import createSagaMiddleware from 'redux-saga';
const sagaMiddleware = createSagaMiddleware();
createStore(reducer, applyMiddleware(sagaMiddleware))
4.2.1 使用 saga 接收 action 执行异步操作
saga 文件中需要从 redux-saga/effects
中引入两个方法
takeEvery
:用于接收 action,也就是说当组件去触发一个 action 的时候,saga 文件中可以通过 takeEvery 去接收这个 action- 第一个参数:要接收的 action 的类型字符串
- 第二个参数:当接收到这个 action 以后需要执行的方法(也是 Generator 函数,里面写异步操作的代码)
put
:用于触发另外一个 action,当异步操作执行完成返回结果以后,需要通过 put 方法去触发一个 action,将异步操作的结果传递给 reducer,reducer 再将数据保存到 store 中。put 的作用跟 dispatch 方法是一样的
在 saga 文件中,要求默认导出一个 generator 函数
import { takeEvery, put } from 'redux-saga/effects';
function* load_posts() {
const { data } = yield axios.get('/api/posts.json');
yield put(load_posts_success(data));
}
export default function* postSaga() {
yield takeEvery(LOAD_POSTS, load_posts);
}
4.2.2 启用 saga
引入 saga 文件之后,需要使用 sagaMiddleware.run()
方法启用 saga 文件
import postsSaga from './store/sagas/posts.saga';
sagaMiddleware.run(postsSaga);
4.2.3 示例
components/counter.jsx
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as counterActions from '../store/actions/counter.actions';
function Counter({ count, decrement, increment, increment_async }) {
return (
<div>
<button onClick={() => decrement(5)}>-</button>
<span>{count}</span>
<button onClick={increment_async}>+</button>
</div>
);
}
const mapStateToProps = (state) => ({
count: state.counter.count
});
const mapDispatchToProps = (dispatch) =>
bindActionCreators(counterActions, dispatch);
// connect 方法接收一个函数,这个函数的参数是 store 中的 state,返回一个对象,这个对象会被映射到组件的 props 属性中
// connect 方法返回一个函数,该函数需要接收一个组件(需要使用到 store 状态的组件)
export default connect(mapStateToProps, mapDispatchToProps)(Counter);
store/sagas/counterSaga.js
import { delay, put, takeEvery } from 'redux-saga/effects';
import { increment } from '../actions/counter.actions';
import { INCREMENT_ASYNC } from '../const/counter.const';
function* increment_async_fn() {
yield delay(2000); // delay 是 redux-saga 提供的延迟函数
yield put(increment(10));
}
export default function* counterSaga() {
yield takeEvery(INCREMENT_ASYNC, increment_async_fn);
}
store/index.js
import { applyMiddleware, createStore } from 'redux';
import createSagaMiddleware from 'redux-saga';
import reducer from './reducers/root.reducer';
import counterSaga from './sagas/counterSaga';
const sagaMiddleware = createSagaMiddleware();
const store = createStore(
reducer,
/* 这里本来是 reducer 的默认参数,但是它是可选的, 所以可以将 applyMiddleware 放在第二个参数上 */
applyMiddleware(sagaMiddleware)
);
sagaMiddleware.run(counterSaga);
export default store;
4.2.4 redux-saga 传参
// component
<button onClick={()=>increment_async(20)}>+</button>
// action
export const increment_async = (payload) => ({ type: INCREMENT_ASYNC, payload });
// saga
function* increment_async_fn(action) {
yield delay(2000);
yield put(increment(action.payload));
}
export default function* counterSaga() {
yield takeEvery(INCREMENT_ASYNC, increment_async_fn);
}
4.2.5 redux-saga 的拆分和合并
counter.saga.js
import { delay, put, takeEvery } from 'redux-saga/effects';
import { increment } from '../actions/counter.actions';
import { INCREMENT_ASYNC } from '../const/counter.const';
function* increment_async_fn(action) {
yield delay(2000);
yield put(increment(action.payload));
}
export default function* counterSaga() {
yield takeEvery(INCREMENT_ASYNC, increment_async_fn);
}
modal.saga.js
import { delay, put, takeEvery } from 'redux-saga/effects';
import { show } from '../actions/modal.action';
import { SHOW_MODAL_ASYNC } from '../const/modal.const';
function* showModal_async_fn() {
yield delay(2000);
yield put(show());
}
export default function* modalSaga() {
yield takeEvery(SHOW_MODAL_ASYNC, showModal_async_fn);
}
root.saga.js
import { all } from 'redux-saga/effects';
import counterSaga from './counter.saga';
import modalSaga from './modal.saga';
function* rootSaga() {
// all 方法传入数组,数组元素为 saga 的调用
yield all([counterSaga(), modalSaga()]);
}
export default rootSaga;
最后将 rootSaga 传入 saga.run 方法中
import { applyMiddleware, createStore } from 'redux';
import createSagaMiddleware from 'redux-saga';
import reducer from './reducers/root.reducer';
import rootSaga from './sagas/root.saga';
const sagaMiddleware = createSagaMiddleware();
const store = createStore(
reducer,
/* 这里本来是 reducer 的默认参数,但是它是可选的, 所以可以将 applyMiddleware 放在第二个参数上 */
applyMiddleware(sagaMiddleware)
);
sagaMiddleware.run(rootSaga);
export default store;
4.3 redux-actions
redux-actions 可以简化 Action 和 Reducer 的使用
- 安装:
npm install redux-actions
- 引入:
import { createAction } from 'redux-actions';
- 注册:
4.3.1 createAction 方法的使用
- createAction 是 redux-actions 中间件提供的一个方法,用于简化 action。它接收一个字符串,这个字符串是 action 对象里面的 TYPE 属性值;它的返回值就是 actionCreator 函数
import { createAction } from 'redux-actions';
export const increment = createAction('increment');
export const decrement = createAction('decrement');
- 使用 createAction 方法创建 actionCreator 的好处:在创建和触发 action 的时候,只需要使用 createAction 方法的返回值就可以了,不需要再将 action 的 TYPE 值抽象成常量
4.3.2 handleActions 方法的使用
- handleActions 方法的作用就是:接收 action,处理 action,实际上这个方法的返回值就是之前我们自己创建的 reducer 函数
import { handleActions as createReducer } from 'redux-actions';
import { decrement, increment } from '../actions/counter.actions';
const initialState = { count: 0 };
const handleIncrement = (state, action) => ({
count: state.count + action.payload
});
const handleDecrement = (state, action) => ({
count: state.count - action.payload
});
export default createReducer(
{
[increment]: handleIncrement,
[decrement]: handleDecrement
},
initialState
);