Redux 是 JavaScript 状态容器,提供可预测化的状态管理。可以让你构建一致化的应用,运行于不同的环境(客户端、服务器、原生应用),并且易于测试。不仅于此,它还提供超爽的开发体验,比如有一个时间旅行调试器可以编辑后实时预览。Redux 除了和 React 一起用外,还支持其它界面库。
工作流程
Redux工作流程:
- View在redux中会派发action方法
- action通过store的dispatch方法会派发给store
- store接收action,连同之前的state,一起传递给reducer
- reducer返回新的数据给store
- store去改变自己的state
场景演示
引用图书馆场景
- React Component:借书的用户
- Action Creators: 借什么书(这句话)
- Store:图书馆管理员
- Reducers: 记录本(书籍的记录)
小K(React Component)对图书馆管理员(Store)说:借一本 ‘XX’(Action Creators),管理员通过记录本(Reducers)去找这本书,找到之后把书给到小K。
获取数据 :一个组件去获取 Store 中的数据,对 Store 说:我要获取XX数据(Action Creators创建这句话),Store 接收到后,通过 Reducers 去找到这条数据,然后把数据给到这个组件。
改变数据 :同理 Store 通过 Reducers 知道如何改变数据,然后 Store 修改好数据后,告诉组件数据已修改,可以重新获取数据了。
代码演示
上图展示了redux数据的基本流程,简单的说就是view dispatch一个action后,通过对应reducer处理,然后更新store,最终views根据store数据的改变重新渲染界面。
Store
store就是redux的一个数据中心,简单的理解就是我们所有的数据都会存放在里面,然后在界面上使用时,从中取出对应的数据。因此最开始,我们要创建一个这样的store,redux提供了createStore方法。
Store 有以下职责:
- createStore 可以帮助我们创建一个store
- store.dispatch 帮助我们派发action 这个action会传递给store
- store.getState 获取到store里面所有的数据内容
- store.subscribe 可以让我们订阅(监听) store的改变 只要store发生改变, 这个方法的回调函数就会执行
/store/index.js
import { createStore } from 'redux'
import reducer from './reducer'
const store = createStore(reducer)
export default store
Action
Action 是把数据从应用传到 store 的有效载荷。它是 store 数据的唯一来源。一般来说你会通过 store.dispatch() 将 action 传到 store。
//添加新 todo 任务的 action 是这样的:
export const ADD_TODO = 'ADD_TODO';
{
type: ADD_TODO,
text: 'Build my first Redux app'
}
// action 创建函数
export function addTodo(text) {
return { type: ADD_TODO, text }
}
上面代码中,addTodo函数就是一个 Action Creator。
// 发起action
store.dispatch(addTodo('Build my first Redux app'))
store 里能直接通过 store.dispatch() 调用 dispatch() 方法,但是多数情况下你会使用react-redux 提供的 connect() 帮助器来调用。 bindActionCreators() 可以自动把多个action 创建函数绑定到 dispatch() 方法上。
Reducer
Reducers 指定了应用状态的变化如何响应 actions 并发送到 store 的,记住 actions 只是描述了有事情发生了这一事实,并没有描述应用如何更新 state。
Reducer 是一个函数,它接受 Action 和当前 State 作为参数,返回一个新的 State 。
/store/reducer.js
function reducer(state, action) {
// 这里暂不处理任何 action,
// 仅返回传入的 state。
return state
}
为了让用户监听应用数据改变,Store 允许使用store.subscribe方法设置监听函数,一旦 State 发生变化,就自动执行这个函数。
constructor(props) {
super(props)
store.subscribe(this.xxx.bind(this))
//只要 store 中的数据发生改变,subscribe 中的 xxx 会自动执行
}
这里需要再强调一下:Redux 和 React 之间没有关系。Redux 支持 React、Angular、Ember、jQuery 甚至纯 JavaScript。
Connect
connect()是react-redux中的核心方法之一,它将react组件预redux中的Store真正连接在一起。
Provider和Connect
provider使组件层级中的 connect() 方法都能够获得 Redux store。
ReactDOM.render(
<Provider store={store}>
<App/>
</Provider>
)
connect()签名
connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])
[mapStateToProps(state, [ownProps]): stateProps] (Function):
- mapStateToProps必须是一个Function,作用是绑定state的指定值到props上
- state: 监听Redux store的变化。任何时候只要 Redux store发生改变,mapStateToProp 函数就会被调用,该回调函数必须返回一个纯对象,该对象会与相应展示组件的 props 合并
- ownProps: 该参数的值为传递到组件的 props,而且只要组件接收到新的props,mapStateToProps 也会被调用
[mapDispatchToProps(dispatch, [ownProps]): dispatchProps] (Object or Function)
- mapDispatchToProps可以是一个Function,也可以是Object,作用是绑定action创建函数到props上
dispatch: - 如果传递的是一个对象,那么每个定义在该对象的函数都将被当作Redux action creator,而且这个对象会与 Reduxstore绑定在一起,其中所定义的方法名将作为属性名,合并到组件的 props 中;
- 如果传递的是一个函数,该函数将接收一个 dispatch 函数,然后由你来决定如何返回一个对象,这个对象通过 dispatch 函数与action creator 以某种方式绑定在一起
[mergeprops(stateprops,dispatchProps,ownProps):props)
- 之前说过,不管是stateprops还是dispatchprops,都需要和onprops merge之后才会被赋给wComp。connect的第三个参数就是用来做这件事。通常情况下,你可以不传这个参数,connect就会使用 object.assign代该方法。
其他
- 最后还有options选项,比较简单,基本上也不大会用到。
要点
应用中所有的 state 都以一个对象树的形式储存在一个单一的 store 中。 惟一改变 state 的办法是触发 action,一个描述发生什么的对象。 为了描述 action 如何改变 state 树,你需要编写 reducers。
就是这样!
import { createStore } from 'redux';
/**
* 这是一个 reducer,形式为 (state, action) => state 的纯函数。
* 描述了 action 如何把 state 转变成下一个 state。
*
* state 的形式取决于你,可以是基本类型、数组、对象、
* 甚至是 Immutable.js 生成的数据结构。惟一的要点是
* 当 state 变化时需要返回全新的对象,而不是修改传入的参数。
*
* 下面例子使用 `switch` 语句和字符串来做判断,但你可以写帮助类(helper)
* 根据不同的约定(如方法映射)来判断,只要适用你的项目即可。
*/
function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
}
// 创建 Redux store 来存放应用的状态。
// API 是 { subscribe, dispatch, getState }。
let store = createStore(counter);
// 可以手动订阅更新,也可以事件绑定到视图层。
store.subscribe(() =>
console.log(store.getState())
);
// 改变内部 state 惟一方法是 dispatch 一个 action。
// action 可以被序列化,用日记记录和储存下来,后期还可以以回放的方式执行
store.dispatch({ type: 'INCREMENT' });
// 1
store.dispatch({ type: 'INCREMENT' });
// 2
store.dispatch({ type: 'DECREMENT' });
// 1
安装
Redux 官方提供的 React 绑定库。 具有高效且灵活的特性。
npm install --save react-redux
yarn add react-redux
使用场景
- 某个组件的状态,需要共享;
- 某个状态需要在任何地方都可以拿到;
- 一个组件需要改变全局状态;
- 一个组件需要改变另一个组件的状态。