在 react 中 引入 redux 可以实现状态管理, 但有些地方有点冗余,所以 react 肯定是会解决这个问题的,所以这次总结 react-redux ,这个库是用来连接 react 和 redux 的
具体使用步骤如下:
1 安装 react-redux
npm install react-redux –save
2 引入 react-redux
index.js :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import React from 'react'; import { render } from 'react-dom'; import { Provider } from 'react-redux'; import store from './store';
import TodoList from './components/TodoList'; import Counter from './components/Counter';
render( <Provider store={store}> <Counter /> <TodoList /> </Provider>, window.root );
|
注意:
1 Provider:哪个组件需要使用它,就把那个组件放在它里面,它也是一个组件
2 store:是要传进去的store
3 connect
放在 Provider 里的组件要调用这个方法,用来连接store
component/counter.js :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| import React, { Component } from 'react'; import { bindActionCreators } from 'redux'; import {connect} from 'react-redux';
import * as actions from '../store/actions/counter';
class Counter extends Component {
render () { return ( <div> { this.props.count } <button onClick={ this.handleClick }>add</button> </div> ) }
handleClick = () => { this.props.add(6) } }
const mapStateToProps = (state) => state.counter;
export default connect(mapStateToProps, actions)(Counter);
|
store/reducers/counter.js :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import * as Types from '../actionTypes';
const initState = { count: 0 }
export default (state=initState, action) => { const newState = JSON.parse( JSON.stringify(state));
switch (action.type) { case Types.COUNT_ADD: newState.count = newState.count + action.n; return newState; }
return state; }
|
store/actions/counter.js :
1 2 3 4 5 6 7 8
| import * as Types from '../actionTypes';
export const add = (n) => { return { type: Types.COUNT_ADD, n } }
|
注意:
1 connect:接收两个参数:mapStateToProps,mapDispatchToProps
2 mapStateToProps:把要订阅store中的哪个值传进去
3 mapDispatchToProps:调用的是哪个action 传进去
4 这样在点击事件 handleClick 中就可以通过 this.props调用 store 中的方法,this.props.add(5)
到这里,react-redux 的使用步骤大体是这样的,这个过程发现 代码都是有问题解决问题,再进一步优化再优化!
4 redux-thunk、redux-promise、redux-logger、redux-saga 中间介
当我们在组件中需要获取一些初始数据,这些数据并不是自己私有的,是需要传给store的,而这些数据最初是通过axios等异步方式获取时,我们可以把这个axios方法写在 componentDidMount 方法中,但这样这个过程是:组件在 componentDidMount 获取数据,通过 dispatch 传给 store
既然是这样,那干嘛不直接在 store 中去获取
store/actions/todoList.js :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| import * as Types from '../actionTypes'; import axios from 'axios';
export const getInitList = list => {
}
|
嗯,react 是一个成熟的框架,它显然可以通过别的方式在 store 中获取,配和redux 中的 redux-thunk、redux-promise 可以实现
redux-thunk
安装:npm install redux-thunk –save
store/index.js :
1 2 3 4 5 6 7 8 9 10
| import { createStore, applyMiddleware } from 'redux'; import reducer from './reducers'; import thunk from 'redux-thunk';
const store = createStore( reducer, applyMiddleware(thunk) );
export default store;
|
store/actions/todoList.js :
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import * as Types from '../actionTypes'; import axios from 'axios';
export const getInitList = list => {
return dispatch => { axios.get('list.json').then(res => { dispatch({ type: Types.GET_INIT_LIST, list: res }) }) } }
|
redux-promise
安装:npm install redux-promise –save
store/index.js :
1 2 3 4 5 6 7 8 9 10 11
| import { createStore, applyMiddleware } from 'redux'; import reducer from './reducers'; import thunk from 'redux-thunk'; import promise from 'redux-promise';
const store = createStore( reducer, applyMiddleware(thunk, promise) );
export default store;
|
store/actions/todoList.js :
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import * as Types from '../actionTypes'; import axios from 'axios';
export const getInitList = list => { return new Promise( (resolve, reject) => { axios.get('list.json').then(res => { resolve({ type: Types.GET_INIT_LIST, list: res }) }) }) }
|
redux-logger
这个中间介 是为了知道在任务派发之前和派发之后的一个状态
安装:npm install redux-logger –save
store/index.js :
1 2 3 4 5 6 7 8 9 10 11 12
| import { createStore, applyMiddleware, compose } from 'redux'; import reducer from './reducers'; import thunk from 'redux-thunk'; import promise from 'redux-promise'; import logger from 'redux-logger';
const store = createStore( reducer, applyMiddleware(thunk, promise, logger) );
export default store;
|
这时候就可以在控制台看到任务派发前和派发后的状态,如下:
在前面的 index.js 中把 window那一句删除了,但它是用来在控制台打开 redux 的,现在把它加回来,这个在github上有使用说明
index.js :
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import { createStore, applyMiddleware, compose } from 'redux'; import reducer from './reducers'; import thunk from 'redux-thunk'; import promise from 'redux-promise'; import logger from 'redux-logger';
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore( reducer, composeEnhancers( applyMiddleware(thunk, promise, logger) ) );
export default store;
|
redux-saga
这个中间介作用和 redux-thunk 一样,也是在 action 中可以调用一次网络请求,但使用的方式有很大不同
安装:npm install redux-saga –save
store/index.js :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import { createStore, applyMiddleware } from 'redux'; import reducer from './reducers'; import createSagaMiddleware from 'redux-saga'; import mySaga from './sagas';
const sagaMiddleware = createSagaMiddleware();
const store = createStore( reducer, applyMiddleware(sagaMiddleware) );
sagaMiddleware.run(mySaga);
export default store;
|
store/sagas.js , 在这个文件中集中处理对异步的请求,它能够感知到每一次任务派发的请求,当派发某个任务时,这里就执行相应的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| import { takeEvery, put } from 'redux-saga/effects'; import axios from 'axios'; import * as Types from './actionTypes'; import * as actions from './actions/todoList';
function* mySaga () { yield takeEvery(Types.ADD_TODO_ITEM, addItem); yield takeEvery(Types.GET_TODO_DATA, getTodoData); }
function* addItem () { console.log('add'); }
function* getTodoData () { try { const data = yield axios.get('list.json'); const action = actions.getInitList(data); yield put(action); } catch (err) { console.log(err); } }
export default mySaga;
|
component/todoList.js :
1 2 3
| componentDidMount () { this.props.getTodoData(); }
|
这四个中间介是目前我了解到的,基本区别如下:
redux-thunk:帮助action接受函数,能在redux发送一次异步请求
redux-promise:帮助action接收promise
redux-logger:了解派发之前和派发之后的状态
redux-saga:和redux-thunk有点相似,也能在redux中发送一次异步请求,但两者使用方式有很大不同