Redux
简介
Redux是一个JavaScript状态容器,提供可预测化的状态管理
诞生
由于react是单向数据流,这就意味着在一个数据状态非常复杂的应用,react无法实现让两个组件之间互相交流,使用对方的数据,此时,就需要一个机制,把所有的state集中到组件顶部,能够灵活的将所有的state各取所需的分发给各个组件,这就是redux诞生的原因
原理
- redux会将整个应用状态存储到到一个地方,称为store,这个store里面保存一棵状态树。
- 组件改变state的唯一方法是通过调用store的dispatch方法,触发一个action,这个action被对应的reducer处理,完成state更新。
- 各个组件可以订阅store中的状态(state)来刷新自己的视图。
核心
- reducer:用来处理action,通过传入旧的state和action来指明如何更新state,并返回新的state。
- action:用来传递操作state的信息到store,是store的唯一来源,以对象形式存在(type字段必须存在)。
- store:action用来描述发发生了什么,reducer根据action更新state,store就是把这几样东西连接到一起的对象。
三大原则
- 单一数据源:整个应用的state被储存在一棵object tree中,并且这个object tree只存在于唯一一个store中。
- state是只读的:唯一改变state的方法就是触发action,action是一个用于描述已发生事件的普通对象。
- 使用纯函数修改:为了描述action如何改变state tree,你需要编写reducers,reducers只是一些纯函数,它接收先前的state和action,并返回新的state。
实现
// store/reducers/count.js
cosnt initialState = {
count: 0
}
export default (state = initialState, action) => {
switch (action.type) {
case 'INCREASE':
return { count: state.count + 1 };
case 'DECREASE':
return { count: state.count - 1 };
default:
return state;
}
}
// store/actions/count.js
export const reducer = data => ({
type: 'INCREASE',
data
});
export const decrease = data => ({
type: 'DECREASE',
data
});
// store/index.js
import { combineReducers, createStore } from 'redux';
import countStore from './reducers/count.js';
const reducer = combineReducers({
countStore,
});
export default createStore(reducer);
// pages.js
import store from './store';
import * as countActions from '@/store/count';
const AppView = props => {
const count = store.getState();
store.dispatch(countActions.reducer());
store.dispatch(countActions.decrease());
}
React-Redux
简介
react-redux是redux官方提供的react绑定库,具有高效且灵活的特性,它可以把redux的store直接集成到react应用的顶层props中,这样我们只要保证各个子组件能访问到顶级props,就可以实现在各个子组件访问redux数据了
核心
- Provider:这个组件的目的是让所有组件都能够访问到redux中的数据
- connect:connect(mapStateToProps, mapDispatchToProps)(MyComponent),mapStateToProps的作用是把state映射到props中去,mapDispatchToProps的作用是把dispatch映射到props中去,这样我们就可以在props中去访问redux中的数据及触发action了
实现
// index.js
import { Provider } from 'react-redux';
import store from './store';
<Provider store={store}>
<App />
<Provider>
// page.js
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as countActions from '@/store/count';
const AppView = props => {
const count = props.count;
props.countActions.reducer();
props.countActions.decrease();
}
export default connect(
({ countStore }) => ({
count: countStore.count
}),
dispatch => ({
countActions: bindActionCreators(countActions, dispatch)
})
)(AppView)