1、redux
安装
npm i redux
what
- 某个组件的状态,需要让其他组件可以随时拿到(共享)
- 一个组件需要改变另一个组件的状态(通信)
- 总体原则:能不用就不用
工作流程图
核心概念
1、action
- 1、动作的对象
- 2、包含2个属性
- type:标识属性, 值为字符串, 唯一, 必要属性
- data:数据属性, 值类型任意, 可选属性
- 3、例子:{ type: ‘ADD_STUDENT’,data:{name: ‘tom’,age:18} }
2、reducer
- 1、用于初始化状态、加工状态。
- 2、加工时,根据旧的state和action, 产生新的state的****纯函数********。****
3、store
- 1、将state、action、reducer联系在一起的对象
- 2、如何得到此对象?
-
- import {createStore} from ‘redux’
-
- import reducer from ‘./reducers’
-
- const store = createStore(reducer)
-
- 3、此对象的功能?
-
- getState(): 得到state
-
- dispatch(action): 分发action, 触发reducer调用, 产生新的state
-
- subscribe(listener): 注册监听, 当产生了新的state时, 自动调用
-
使用
精简版
-
(1).去除Count组件自身的状态
-
(2).src下建立:
- -redux
- -store.js
- -count_reducer.js
- -redux
-
(3).store.js:
-
1).引入redux中的createStore函数,创建一个store
-
2).createStore调用时要传入一个为其服务的reducer
-
3).记得暴露store对象
/** * 该文件专门用于暴露一个store对象,整个应用只有一个store对象 */ import { createStore } from "redux"; //引入为count组件所服务的reducer import countReducer from './count_reducer'; const store = createStore(countReducer); export default store;
-
-
(4).count_reducer.js:
-
1).reducer的本质是一个函数,接收:preState,action,返回加工后的状态
-
2).reducer有两个作用:初始化状态,加工状态
-
3).preState为数组时不能直接使用.shifit.push,因为会出现浅拷贝
-
4).reducer被第一次调用时,是store自动触发的:
- 传递的preState是undefined,
- 传递的action是:{type:’@@REDUX/INIT_a.2.b.4}
/** * 该文件用于创建一个为Count组件服务的reducer,本质为函数 * reuducer会接收两个参数,之前的状态(preState),动作对象(action) */ const initState = 0; const countReducer = (preState = initState, action) => { //从action中获取,type、data const {type, data} = action; switch (type) { case 'increment': //如果是+ return preState + data; case 'decrement': return preState - data; default: return preState; } }; export default countReducer;
-
-
(5).在index.js中监测store中状态的改变,一旦发生改变重新渲染
备注:redux只负责管理状态,至于状态的改变驱动着页面的展示,要靠我们自己写。//index.js import store from './redux/store'; store.subscribe(() => { ReactDOM.render( < App /> , document.getElementById('root')); });
-
(6).获取store的值:store.getState()
-
(7).向store提交方法:store.dispatch({ ‘type’: ‘decrement’, data: value * 1 });
完整版
新增文件:
-
1.count_action.js 专门用于创建action对象
/** * 该文件专门为count组件生成action对象 */ export const createIncrementAction = (data) => { return {type: 'increment', data}; }; export const createDecrementAction = (data) => { return {type: 'decrement', data}; };js
-
2.constant.js 放置容易写错的type值
异步action
-
action
-
object:同步
-
function:异步
-
-
安装redux-thunk
npm i redux-thunk
-
在store.js中添加条件
import { createStore, applyMiddleware } from "redux"; //引入redux-thunk,用于支持异步action import thunk from 'redux-thunk'; const store = createStore(countReducer, applyMiddleware(thunk));
-
创建异步action
//异步任务 export const createIncrementAsyncAction = (data, time) => { return (dispatch) => { setTimeout(() => { dispatch(createIncrementAction(data)); }, time); }; };
-
异步action默认会调用同步action
2、react-redux
安装
npm i react-redux
原理图
项目构成
- pages--------路由组件
- components-------------UI组件
- container----------------容器组件
基本使用
-
1、index.js中去除store.subscribe,不需要进行监听,引入Provider,并包裹App
import { Provider } from 'react-redux'; ReactDOM.render( <Provider store={store}> < App /> </Provider> , document.getElementById('root'));
-
2、创建container文件夹,并创建容器组件
-
3、在App.jsx中引入容器组件,并传入对应的store
import store from './redux/store'; <div> <Count /> </div>
-
4、在容器组件中引入UI组件、react-redux、store的action
// 引入Count的UI组件 import CountUI from "../../components/Count"; // 引入connect用于连接UI组件与redux import { connect } from "react-redux"; //引入action import { createIncrementAction } from "../../redux/count_action";
-
5、创建mapStateToProps、mapDispatchToProps两个函数
-
mapStateToProps
-
返回的对象中的key作为传递给UI组件props的key,value作为值------状态
-
state为store传过来的,默认调用了store.getState()
-
映射状态
const mapStateToProps = state => ({count: state}); /*const mapStateToProps = (state) => { return { count: state }; };*/
-
-
mapDispatchToProps
-
返回的对象中的key作为传递给UI组件props的key,value作为方法------方法
-
默认传了store.dispatch
-
映射操作状态的方法
-
也可以是**对象 **
const mapDispatchToProps = dispatch => ({ increment(value) { dispatch(createIncrementAction(value)); }, }); /*const mapDispatchToProps = (dispatch) =>{ return { increment(value) { dispatch(createIncrementAction(value)); }, }; };*/
-
-
-
6、使用connect创建一个Count的容器组件
export default connect(mapStateToProps, mapDispatchToProps)(CountUI); //简写 export default connect( state => ({count: state}), { increment: createIncrementAction,//前提createIncrementAction需引入 })(CountUI);
-
7、在UI组件中使用值时用props中的值与方法
this.props.increment(value * 1); this.props.count
UI组件和容器组件的整合
-
将需要用store的UI组件和容器组件写在一个文件中
-
container的index.jsx
// 引入connect用于连接UI组件与redux import { connect } from "react-redux"; //引入action import { createIncrementAction, createDecrementAction, createIncrementAsyncAction } from "../../redux/count_action"; import React, { Component } from 'react'; class Count extends Component {....} export default connect( state => ({ count: state }), { increment: createIncrementAction, decrement: createDecrementAction, incrementAsync: createIncrementAsyncAction } )(Count);
3、组件间传递
-
1、创建容器组件以及其action、reducer
-
2、store.js中
import { createStore, applyMiddleware, combineReducers } from "redux"; //引入redux-thunk,用于支持异步action import thunk from 'redux-thunk'; //引入为count组件所服务的reducer import countReducer from './Count/count_reducer'; //引入为person服务的reducer import personReducer from "./Person/person_reducer"; //汇总reducer //combineReducers传入的对象就是redux保存的总状态对象 const allReducer = combineReducers({ count: countReducer, personArr: personReducer, }); const store = createStore(allReducer, applyMiddleware(thunk)); export default store;
-
容器组件中获取state
export default connect( state => ({ personArr: state.personArr, count: state.count }),//映射状态 { addPerson: createAddPersonAction } //映射操作状态的方法 )(Person);
4、redux-devtools
安装
npm i redux-devtools-extension
使用
//引入redux-devtools-extension
import { composeWithDevTools } from "redux-devtools-extension";
const store = createStore(allReducer, composeWithDevTools(applyMiddleware(thunk)));