Redux 是什么,如何用?
Redux
是 JavaScript
状态容器,提供可预测化的状态管理。可以让你构建一致化的应用,运行于不同的环境(客户端、服务器、原生应用),并且易于测试。不仅于此,它还提供超爽的开发体验,比如有一个时间旅行调试器可以编辑后实时预览。Redux
除了和 React
一起用外,还支持其它界面库。
redux的核心原理是什么?
- 将应用的状态统一放到
state
中,由store
来管理state
。 reducer
的作用是返回一个新的state
去更新store
中对用的state
。- 按
redux
的原则,UI
层每一次状态的改变都应通过action
去触发,action
传入对应的reducer
中,reducer
返回一个新的state
更新store
中存放的state
,这样就完成了一次状态的更新 subscribe
是为store
订阅监听函数,这些订阅后的监听函数是在每一次dipatch
发起后依次执行- 可以添加中间件对提交的
dispatch
进行重写
工作流程
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 creato
r 以某种方式绑定在一起
[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
使用场景
- 某个组件的状态,需要共享;
- 某个状态需要在任何地方都可以拿到;
- 一个组件需要改变全局状态;
- 一个组件需要改变另一个组件的状态。