从react到react-redux到react-redux-react-redux
原文链接:链接描述https://github.com/jimwmg/JiM... 前言,对于初学者来说,这个demo理解起来相对简单,只需要create-react-app,然后 npm install react-redux npm install redux 即可.(react官方文档和redux官方文档) 本文主要理解redux在react中期的作用,以及react-redux如何将react和redux连接起来 Provider connect 源码解读 createStore源码 Provider connect2 源码解读 一个比较好的案例 ReactDOM.render源码解析 1 react 通过setState改变state状态,触发ReactDOM.render函数,重新刷新UI组件 import React,{Component,PropTypes} from 'react' import ReactDOM from 'react-dom' class Toggle extends React.Component { constructor(props) { super(props); this.state = {count: 1}; // This binding is necessary to make `this` work in the callback this.handleClick = this.handleClick.bind(this); } handleClick() { this.setState(prevState => ({ count: prevState.count+1 })); } render() { return ( <button onClick={this.handleClick}> {this.state.count} </button> ); } } console.dir(Toggle); ReactDOM.render( <Toggle />,document.getElementById('root') ); 2 react-redux 通过给store注册render函数,每次dispatch的时候,都会触发render函数(dispatch函数执行的时候,会执行传入的reducer和绑定的所有的监听函数 ) import React,PropTypes} from 'react' import ReactDOM from 'react-dom' import {createStore} from 'redux' const increaseAction = {type :'INCREASE'} function reducer(state = {count: 0},action){ switch(action.type){ case 'INCREASE' : return {count : state.count+1} default : return state } } const store = createStore(reducer) console.log(store); console.log(store.getState()); //=========================如果没有这段代码,视图将不会更新,但是state状态确实是改变了的 function render(){ ReactDOM.render( <Toggle />,document.getElementById('root') ); } store.subscribe(render);//注册监听事件,dispatch函数会执行注册的监听事件;此时的监听事件的作用就是将试图的UI更新,而如果没有触发ReactDOM.render事件,那么UI不会更新; //=========================如果没有这段代码,但是state状态确实是改变了的 class Toggle extends React.Component { render() { return ( <button onClick={()=>{store.dispatch(increaseAction);console.log(store.getState().count); }}> {store.getState().count} </button> ); } } console.dir(Toggle); ReactDOM.render( <Toggle />,document.getElementById('root') ); 3 react redux react-redux 通过第二部分代码我们可以看出来,redux确实可以帮助我们管理代码,但是有一点不好的地方就是每次state的状态改变的时候,都需要重新手动刷新视图. react-redux 提供两个函数,一个是Provider,该组件函数定义的时候,大概实现如下: 可以看出Provider组件可以使得子组件获取到store对象,也就是说可以获取到store对象中的state,dispatch,subscribe等; class Provider extends Component { getChildContext() { return { store : this.props.store }; } render() { return this.props.children; //表示渲染Privider组件的子元素 } } Provider.childContextTypes = { store: React.PropTypes.object } 一个是connect函数 const WrapToggle = connect(mapStateToProps,mapDispatchToProps)(Toggle),高阶组件 该函数的作用是通过mapStateToProps和mapDispatchToProps函数,将将一些属性添加到Toggle组件的props上,同时 当组件第一次加载的时候,给通过Provider组件传递下来的store注册监听事件,该事件的作用就是执行setState函数,从而实现UI的更新,这也就是connect函数的作用之一, 以上三种state改变,触发UI的更新的根本还是通过触发setState函数执行ReactDOM.render函数; import React,PropTypes} from 'react' import ReactDOM from 'react-dom' import {createStore} from 'redux' import {Provider,connect} from 'react-redux' const increaseAction = {type :'INCREASE'} function reducer(state = {count: 0},action){ switch(action.type){ case 'INCREASE' : return {count : state.count+1} default : return state } } const store = createStore(reducer) console.log(store); console.log(store.getState()); class Toggle extends React.Component { //这个组件经过connect之后,就可以访问到通过connect中mapStateToProps,mapDispatchToProps传递到此组件的属性,所有的属性都会挂载到Toggle组件的props对象上; //此时就可以在组件中访问到store整个state状态树中某个对应的state[key],以及store对象中的dispatch函数 //将dispatch函数给到相应的DOM事件,便可以触发分发动作,更新state; //每次更新state之后,都会触发mapStateToProps,更新对应组件上对应的state,同时,对应组件上 render() { console.log(this.props);//connect函数中stateProps dispatchProps ownProps 三者融合后的结果传递给UI组件props对象 //对象的解构赋值 const {value,onIncreaseClick} = this.props return ( <button onClick= {onIncreaseClick}> {value} </button> ); } } const mapStateToProps = (state,ownProps) => { console.log(state); console.log(ownProps); //state就是通过Provider传递进来的store.getState()的结果 //ownProps就是connect返回的新组件,这里是WrapToggle组件上的Props属性对象 return { value: state.count } } const mapDispatchToProps = (dispatch,ownProps) => { console.log(dispatch); console.log(ownProps); //dispatch就是 通过Provider传递进来的store.dispatch函数 //ownProps就是connect返回的新组件,这里是WrapToggle组件上的Props属性对象 return { onIncreaseClick: () => { dispatch(increaseAction) } } } const WrapToggle = connect(mapStateToProps,mapDispatchToProps)(Toggle) console.dir(Toggle); console.dir(WrapToggle); //注意 WrapToggle组件添加了一个属性,方便一会输出对比,这些属性就是ownProps对象 ReactDOM.render( <Provider store={store}> <WrapToggle wrapProps='WarpToggleProps'/> </Provider>,document.getElementById('root') ); 4 react如何响应store的变化,也就是说何时重新渲染页面 4.1 单纯的react中,通过setState函数,改变state状态树,setState函数每次执行都会重新渲染UI视图 4.2 react搭配redux的时候,通过store链接,react的状态可以通过redux来进行管理,此时redux创建的store中存储了react中的state状态,此时如果想要更新UI视图,需要手动绑定事件,此时唯一改变state的函数是dispatch,通过该函数改变state,从createStore源码中可以看出来
4.3 react搭配redux的时候,通过react-redux进行react和redux的连接 ;
默认会将dispatch函数添加到component组件中props属性上. function mapDispatchToProps(dispatch) { return { todoActions: bindActionCreators(todoActionCreators,dispatch),counterActions: bindActionCreators(counterActionCreators,dispatch) }; } //这里面mapDispatchToProps函数接受的参数其实就是store.dispatch函数,bindActionCreators函数接受两个参数,一个是actionCreator,一个是dispatch函数 3)mergeProps(stateProps,dispatchProps,ownProps): 将mapStateToProps() 与 mapDispatchToProps()返回的对象和容器组件自身的props(本案例就是WrapToggle组件的props: wrapProps='WarpToggleProps)合并成新的props并传入被包裹的组件(Toggle)。默认返回 Object.assign({},ownProps,stateProps,dispatchProps) 的结果。 这里也就解释了为什么Toggle组件中props属性中有stateProps,ownProps 这些对象的组合结果了. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |