React-redux深入理解
2017-07-21 22:28
696 查看
首先,一张 Redux 解释图镇楼:
【回顾】Redux 的核心: store 是什么?(createStore 函数的实现)
store 是一个对象,包含3个方法:
由函数可知,当用户
所以,redux 的套路就是(参考 React小书 ):
【问题】:React 和 Redux 之间是如何连接?
从图中可以看到,Store 通过 Provider 传递给了我们的 React 组件,因此,使得组件能够获取到 store。那么它是如何将做到的呢?
为了弄明白 React 和 Redux 之间是如何连接的,我们需要了解以下一些内容(参考 React小书 ):
如果一个组件设置了 context,那么它的子组件都可以直接访问到里面的内容,它就像这个组件为根的子树的全局变量。任意深度的子组件都可以通过 contextTypes 来声明你想要的 context 里面的哪些状态,然后可以通过 this.context 访问到那些状态。
context 存在的问题:首先,它是一个试验性的API,不稳定,可能会改变,虽然好多库都用到了这个特性;其次它是脆弱的,如果在层级中的任何一个组件执行了 shouldComponentUpdate 返回 false,context 则不会传递给其之后所有的子组件。
1. Provider 的实现
作用:充当父组件的作用,把 store 放到自己的 context 里面,让子组件 connect 的时候获取。
2. 高阶组件 connect(connect 实现)
高阶组件:高阶组件是一个接受一个组件为参数,并返回一个被包装过的组件的函数,即返回传入props的原组件。
connect 的作用:和 React 的 context 打交道,将 context 中的数据取出来,并以 prop 的形式传递给 Dumb 组件。
connect 接口:
Redux使用小结
【回顾】Redux 的核心: store 是什么?(createStore 函数的实现)
const store = createStore(reducer);
store 是一个对象,包含3个方法:
getState、
dispatch、
subscribe
// createStore 函数实现 const createStore = (reducer) => { let state; let listeners = []; const getState = () => state; const dispatch = (action) => { state = reducer(state, action); listeners.forEach(listener => listener()); } const subscribe = (listener) => { // listener 就是一个要执行的函数 listeners.push(listener); return () => { // 采用柯里化方式注销监听器,用法:store.subscribe(listener)(); listeners = listeners.filter(l => l != listener); } } dispatch({}); // 初始化state return { getState, dispatch, subscribe } }
由函数可知,当用户
dispatch一个 action 时,会自动调用
reducer从而得到最新的 state,该 state 可通过
getState函数获取,并且会执行所有已注册的函数。
所以,redux 的套路就是(参考 React小书 ):
// 定一个 reducer function reducer (state, action) { /* 初始化 state 和 switch case */ } // 生成 store const store = createStore(reducer) // 监听数据变化重新渲染页面,即更新状态的过程 store.subscribe(() => renderApp(store.getState())) // 首次渲染页面 renderApp(store.getState()) // 后面可以随意 dispatch 了,页面自动更新 store.dispatch(...)
【问题】:React 和 Redux 之间是如何连接?
从图中可以看到,Store 通过 Provider 传递给了我们的 React 组件,因此,使得组件能够获取到 store。那么它是如何将做到的呢?
为了弄明白 React 和 Redux 之间是如何连接的,我们需要了解以下一些内容(参考 React小书 ):
一、背景:React 中父组件 context 的作用,用以摆脱状态提升
在 React 中,父组件使用 getChildContext(),可以将 store 放到它的 context 里面,相当于给子组件设置了一个全局变量,这样每个子组件就都可以获取到 store。// 父组件 class Index extends Component { // 提供 context 的组件必须提供 childContextTypes 作为 context 的声明和验证 static childContextTypes = { store: PropTypes.object } // 一个组件可以通过 getChildContext 方法返回一个对象,这个对象就是子树的 context getChildContext () { return { store } } render () { return ( <div> <Header /> <Content /> </div> ) } } // 子组件 class Header extends Component { // 声明想要的 context 里面的哪些状态,以便通过 this.context 进行访问 // 子组件要获取 context 里面的内容的话,就必须写 contextTypes 来声明和验证你需要获取的状态的类型 static contextTypes = { store: PropTypes.object } constructor () { super() this.state = { themeColor: '' } } componentWillMount () { this._updateThemeColor() } _updateThemeColor () { // 子组件可以访问到父组件 context 里面的内容 const { store } = this.context const state = store.getState() this.setState({ themeColor: state.themeColor }) } render () { return ( <h1 style={{ color: this.state.themeColor }}>React.js 小书</h1> ) } }
如果一个组件设置了 context,那么它的子组件都可以直接访问到里面的内容,它就像这个组件为根的子树的全局变量。任意深度的子组件都可以通过 contextTypes 来声明你想要的 context 里面的哪些状态,然后可以通过 this.context 访问到那些状态。
context 存在的问题:首先,它是一个试验性的API,不稳定,可能会改变,虽然好多库都用到了这个特性;其次它是脆弱的,如果在层级中的任何一个组件执行了 shouldComponentUpdate 返回 false,context 则不会传递给其之后所有的子组件。
二、react-redux 的诞生
因为 context 是一个比较危险的特性,我们不想在自己写组件的时候被其污染,我们需要将其剥离出来,因此,react-redux 诞生了,其中的Provider以及
connect就帮助我们将 React 的组件和 Redux 的 store 进行了连接。
1. Provider 的实现
作用:充当父组件的作用,把 store 放到自己的 context 里面,让子组件 connect 的时候获取。
export class Provider extends Component { static propTypes = { store: PropTypes.object, children: PropTypes.any } static childContextTypes = { store: PropTypes.object } getChildContext () { return { store: this.props.store } } render () { return ( <div>{this.props.children}</div> ) } }
2. 高阶组件 connect(connect 实现)
高阶组件:高阶组件是一个接受一个组件为参数,并返回一个被包装过的组件的函数,即返回传入props的原组件。
connect 的作用:和 React 的 context 打交道,将 context 中的数据取出来,并以 prop 的形式传递给 Dumb 组件。
const mapStateToProps = (state) => { themeColor: state.themeColor } const mapDispatchToProps = (dispatch) => ({ onSwitchColor(color) => { dispatch({ type: 'CHANGE_COLOR', themeColor: color }) } }); // connect 实现 // connect 接受 mapStateToProps 和 mapDispatchProps 参数后,返回的函数是高阶组件,该高阶组件接受一个组件作为参数,然后用 Connect 包装之后返回 export const connect = (mapStateToProps, mapDispatchToProps) => (WrappedComponent) => { class Connect extends Component { static contextTypes = { store: PropTypes.object } constructor () { super() this.state = { allProps: {} } } componentWillMount () { const { store } = this.context this._updateProps() store.subscribe(() => this._updateProps()) } _updateProps () { const { store } = this.context let stateProps = mapStateToProps ? mapStateToProps(store.getState(), this.props) : {} // 防止 mapStateToProps 没有传入 let dispatchProps = mapDispatchToProps ? mapDispatchToProps(store.dispatch, this.props) : {} // 防止 mapDispatchToProps 没有传入 this.setState({ allProps: { ...stateProps, ...dispatchProps, ...this.props } }) } render () { return <WrappedComponent {...this.state.allProps} /> } } return Connect }
connect 接口:
connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])(Component)
三、react-redux 的性能优化
react-redux性能优化之reselect三、文章参考
React小书Redux使用小结
相关文章推荐
- 深入理解React、Redux
- 深入理解React-Redux
- 深入理解react-redux
- 深入理解React、Redux
- 深入理解React、Redux
- [置顶] 深入理解React、Redux
- 深入理解React 高阶组件
- 深入理解React Native页面构建渲染原理
- redux深入理解之中间件(middleware)
- 深入理解Redux:10个来自专家的Redux实践建议
- redux深入理解之中间件(middleware)
- React入门笔记(一) — 深入理解JSX
- 深入理解React(二) —— 数据流和事件原理
- React学习笔记--通过Redux 的三个基本原则来理解Redux
- [转] 深入理解React 组件状态(State)
- 理解 React,但不理解 Redux,该如何通俗易懂的理解 Redux?(转)
- React实战-深入源码了解Redux用法之Middleware
- 深入理解React 组件状态(State)
- 一名iOSer对react-redux的理解
- 深入理解React(二) —— 数据流和事件原理