1.背景介绍
react是单向数据流,一级一级组件传递这个过程是不能越级的,为了解决深度嵌套, redux横空出世
2. redux
安装:npm/cnpm i redux
(1). 分清两个state
Redux中的state和React中的state完全不是一回事,React中的state是组件内部自己的状态信息,而Redux中的state是Redux自己的数据
(2). Redux
redux工作流:
a.store
store:首先要创建一个对象store,这个对象有各种方法,用来让外界获取Redux的数据(store.getState),或者让外界来修改Redux中的数据(store.dispatch)
b.action
action:描述我要干啥,一般是一个对象的形式,其中有一个type字段是必须要有的,比如:{ type:‘撩妹’ },还可以带点数据{ type:‘交朋友’,money: 100 }
c.reducer
reducer: 根据不同的action type处理逻辑
3. React-redux
安装:npm/cnpm i react-redux
在React-redux中有两个比较关键的概念:Provider和connect方法。
a.Provider
一般我们都将顶层组件包裹在Provider组件之中,这样的话,所有组件就都可以在react-redux的控制之下了,但是store必须作为参数放到Provider组件中去。这个组件的目的是让所有组件都能够访问到Redux中的数据。
b.connet
用法:connect(mapStateToProps, mapDispatchToProps)(MyComponent)
mapStateToProps
接收一个state,返回一个对象。 mapDispatchToProps
接收一个 dispatch
组成的对象。
4. demo使用
index.js: provider包含组件最外层,将store传给最顶级组件
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import {Provider} from 'react-redux';
import store from './store/index';
ReactDOM.render(<Provider store={store}><App /></Provider>,
document.getElementById('root')
);
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
store/index.js: combineReducers合并所有模块的reducer; createStore将ruduces转化为store
import {createStore, combineReducers} from 'redux'
import user from './user'
let reduces = combineReducers({
user: user
})
export default createStore(reduces)
store/user.js: 抽象的reducer
import {SET_NAME, ADD_AGE} from '../actions'
function userReducer(state={ name: 'david', age: 18 }, action) {
switch(action.type) {
case SET_NAME:
return {
...state,
name: action.name
};
case ADD_AGE:
return {
...state,
age: state.age + action.age
};
default:
return state;
}
}
export default userReducer
actions.js: 定义type
export const SET_NAME = 'set_name'
export const ADD_AGE = 'add_age'
Home.js: 组件中使用connect, 可以得到redux的state,可以改变state的方法
import React, { Component } from 'react';
import {connect} from 'react-redux';
import {SET_NAME, ADD_AGE} from '../actions';
class Home extends Component {
constructor(...args) {
super(...args);
this.state = {
inputName: ''
}
}
handelChangeName = (e) => {
this.setState({
inputName: e.target.value
})
}
/**
* @description 改变名称
*/
changeName = (e) => {
this.props.setName(this.state.inputName)
}
/**
* @description 改变年龄
*/
changeAge = (e) => {
this.props.addAge(3)
}
render() {
return (
<div>
<div>name: {this.props.name}</div>
<div>age: {this.props.age}</div>
<input type="text" placeholder="请输入名字" value={this.state.inputName} onChange={this.handelChangeName} onBlur={this.changeName}></input>
<button onClick={this.changeAge}>+3</button>
</div>
);
}
}
export default connect((state, props) => {
return state.user
}, {
setName(name){
return {
type: SET_NAME,
name
};
},
addAge(age){
return {
type: ADD_AGE,
age
};
}
})(Home)
或者使用dispatch({type: SET_NAME, name: this.state.inputName}) 也可以达到相同的目的。
import React, { Component } from 'react';
import {connect} from 'react-redux';
import {SET_NAME, ADD_AGE} from '../actions';
class Home extends Component {
constructor(...args) {
super(...args);
this.state = {
inputName: ''
}
}
handelChangeName = (e) => {
this.setState({
inputName: e.target.value
})
}
/**
* @description 改变名称
*/
changeName = (e) => {
// this.props.setName(this.state.inputName)
this.props.dispatch({type: SET_NAME, name: this.state.inputName})
}
/**
* @description 改变年龄
*/
changeAge = (e) => {
// this.props.addAge(3)
this.props.dispatch({type: ADD_AGE, age: 3})
}
render() {
return (
<div>
<div>name: {this.props.name}</div>
<div>age: {this.props.age}</div>
<input type="text" placeholder="请输入名字" value={this.state.inputName} onChange={this.handelChangeName} onBlur={this.changeName}></input>
<button onClick={this.changeAge}>+3</button>
</div>
);
}
}
// export default connect((state, props) => {
// return state.user
// }, {
// setName(name){
// return {
// type: SET_NAME,
// name
// };
// },
// addAge(age){
// return {
// type: ADD_AGE,
// age
// };
// }
// })(Home)
export default connect((state) => {
return state.user
})(Home)
最后推荐使用方式:
import React, {Component} from 'react'
import {connect} from 'react-redux';
import {SET_NAME, ADD_AGE} from '../actions';
class Home extends Component {
constructor(...args){
super(...args)
this.state = {
inputName: ''
}
}
handelChangeName = (e) => {
this.setState({
inputName: e.target.value
})
}
render() {
return (
<div> dashboard
<div>name: {this.props.user.name}</div>
<div>age: {this.props.user.age}</div>
<input type="text" placeholder="请输入名字" value={this.state.inputName} onChange={this.handelChangeName} onBlur={() => this.props.changeName(this.state.inputName)}></input>
<button onClick={this.props.changeAge}>+3</button>
</div>
);
}
}
// 不用装饰器设置 Redux
const mapStateToProps = (state) => {
return { user: state.user }
}
const mapDispatchToProps = (dispatch, ownProps) => ({
changeName: (name) =>
{
dispatch({type: SET_NAME, name: name})
},
changeAge: () => {
dispatch({type: ADD_AGE, age: 3})
}
})
export default connect(mapStateToProps, mapDispatchToProps)(Dashboard)
总结:
I. 单向数据流
state->component->action->state...
II.redux——集中状态管理
provider:包在组件最外面
connect:状态映射
reducer:状态对象
action: 状态更新