redux梳理结果和简单的demo应用
观看react视频教程一段时间,反反复复的看理解写笔记,终于梳理清楚了redux的使用方式,现在做一下梳理:
1.redux不是隶属于react,在react中使用redux需要引入redux react-redux thunk
npm i -S redux react-redux thunk
2.redux用来做全局状态管理,所以全局只有一个store,要让全局所有组件都可以使用store里面的state,需要引入react-redux
提供的Provider组件,将根容器包裹,并且给Provider组件添加一个属性叫做store
//App.js
import { Provider } from 'react-redux';
import store from './store';
import ChangeName from './components/ChangeName';
<Provider store={store}>
<div className='App'>
<ChangeName />
</div>
</Provider>
3.将store单独提取出来,这里需要用到redux
的两个方法createStore
和applyMiddleware
;createStore
是redux原生的方法,用来创建store;applyMiddleware
用来将所有的中间件组成一个数组,一次执行,它接受一个参数middlewares
而这个参数我们可以看见就是引用的thunk
中间件;initialstate是一个初始化的状态;rootReducer是所有reducer的集合(一个数组)
import { createStore , applyMiddleware } from 'redux';
import thunk from 'thunk';
import rootReducer from './reducers/index';
const middlewares = [thunk];
const initialstate = {};
const store = createStore( rootReducer , initialstate , applyMiddleware(...middleware));
export default store;
4.rootReducer
是所有reducer的集合,在./reducers/index
的index文件中采用了redux
的combineReducers
方法,将所有分离的小的reducer合并为一个大的reducer即store里面引用的rootReducer;combineReducers
接收一个参数是一个对象,在这里需要注意的一点是对象的属性名是什么,你在组件里面采用mapStateToProps
方法取state的时候属性名字应该和这个属性名一一对应,譬如下面引用的attrNameReducer
的属性名attrName,在组件中取用的时候如mapStateToProps
中的取法属性名一定要对应
import { combineReducers } from 'redux';
import changeNameReducer from './changeNameReducer';
export default combineReducers({
//属性名与下面的对应
changeName : changeNameReducer
})
const mapStateToProps = state => {
//属性名与上面的对应
changeName : state.changeName
}
5.reducer
是用来更新store的状态的,每一个小的reducer里面,首先会引入action的type类型,最后会暴露一个纯函数(也就是说一旦输入的值是确定的,那么输出的值也是确定的,输出不受任何外界的值的影响),这个纯函数会接受两个参数state
和action
,最后根据这两个参数返回状态值,在rootReducer中会将拆分的小的reducer整合
//changeNameReducer.js
import { CHANGE_NAME } from '../actions/types';
const initialstate = {
defaultData : [], //这里不一定是数组
name : '静静'
}
export default function(state = initialstate , action){
switch (action.type){
case CHANGE_NAME:
return {
...state,
newName : action.payload
}
default:
return state;
}
}
6.reducer本身是不能触发更新store的状态的,它的需要action
来触发,在../actions/types
中会定义各种action的类型,它的同级目录下会定义许多action,每个action中在使用dispatch派发action的时候会指定的action的type类并且带着原先的(或者说还未更新的)state即payload
,派发到reducer中
//types.js
export const CHANGE_NAME = 'CHANGE_NAME';
//changeNameAction.js
import { CHANGE_NAME } from './types';
export const changeNameAction = (data) => dispatch => {
return dispatch({
type : CHANGE_NAME,
payload : data
})
}
7.action
其实只是我们开发人员定义的,真正在用户使用的时候用户是肯定不会懂这些的,用户只会通过组件渲染出来的界面来做出一些行动从而引起我们开发的这些行为.所以说要将我们开发的action
与用户的行为关联起来并且根据用户行为做出对应状态更新,我们就要通过组件来做媒介;在组件中使用react-redux
提供的方法connect
将组件和action关联起来connect( mapStateToProps, { 方法名 })(组件名)
,详细见下面代码的注释
import React, { Component } from 'react';
import { connect } from 'react-redux';
//引入action的方法
import { changeNameAction } from '../action/changeNameAction';
class ChangeName extends Component {
constructor(props){
super(props);
this.changeNameClick = this.changeNameClick.bind(this);
}
changeNameClick(){
this.props.changeNameAction('叶子')
}
render() {
console.log(this.props)
const newName = this.props.changeName.newName;
const name = this.props.changeName.name;
return (
<div>
<button onClick={this.changeNameClick}>触发changeName事件</button>
<p>显示值{newName?newName:name}</p>
</div>
)
}
}
//使用mapStateToProps 来获取store改变的state
const mapStateToProps = state => ({
changeName : state.changeName
})
//采用connect将action与组件关联起来
export default connect( mapStateToProps, { changeNameAction })(ChangeName);
最后我们再来看下面这张图的时候就很清楚了redux到底是怎么实现的
redux应用图解