详解react、redux、react-redux之间的关联

本文引见了react、redux、react-redux之间的关联,分享给人人,也给本身留个笔记,详细以下:

React

一些小型项目,只运用 React 完整够用了,数据管理运用props、state即可,那什么时刻须要引入Redux呢? 当衬着一个组件的数据是经过过程props从父组件中猎取时,通常状况下是 A –> B,但随着营业复杂度的增添,有多是如许的:A –> B –> C –> D –> E,E须要的数据须要从A那边经过过程props通报过来,以及对应的 E –> A逆向通报callback。组件BCD是不须要这些数据的,然则又必需经过它们来通报,这确切有点不爽,而且通报的props以及callback对BCD组件的复用也会形成影响。或许兄弟组件之间想要同享某些数据,也不是很随意马虎通报、猎取等。诸如此类的状况,就有必要引入Redux了。

实在 A –> B –> C –> D –> E 这类状况,React不运用props层层通报也是能拿到数据的,运用Context即可。背面要讲到的react-redux就是经过过程Context让各个子组件拿到store中的数据的。

Redux

实在我们只是想找个处所寄存一些同享数据罢了,人人都可以猎取到,也都可以举行修正,仅此罢了。 那放在一个悉数变量内里行不可?行,固然行,然则太不文雅,也不平安,因为是全局变量嘛,谁都能接见、谁都能修正,有可以一不小心被哪一个小伙伴覆蓋了也说不定。那全局变量不可就用私有变量呗,私有变量、不能随意马虎被修正,是否是立马就想到闭包了…

如今要写如许一个函数,其满足:

寄存一个数据对象
外界能接见到这个数据
外界也能修正这个数据
当数据有变化的时刻,关照定阅者


function createStore(reducer, initialState) {
 // currentState就是谁人数据
 let currentState = initialState;
 let listener = () => {};
 
 function getState() {
 return currentState;
 }
 function dispatch(action) {
 currentState = reducer(currentState, action); // 更新数据
 listener(); // 实行定阅函数
 return action;
 }
 function subscribe(newListener) {
 listener = newListener;
 // 作废定阅函数
 return function unsubscribe() {
  listener = () => {};
 };
 }
 return {
 getState,
 dispatch,
 subscribe
 };
}
 
const store = createStore(reducer);
store.getState(); // 猎取数据
store.dispatch({type: 'ADD_TODO'}); // 更新数据
store.subscribe(() => {/* update UI */}); // 注册定阅函数

更新数据实行的步骤:

What:想干什么 — dispatch(action)
How:怎样干,干的效果 — reducer(oldState, action) => newState
Then?:从新实行定阅函数(比方从新衬着UI等)
如许就完成了一个store,供应一个数据存储中间,可以供外部接见、修正等,这就是Redux的重要头脑。 所以,Redux确切和React没有什么实质关联,Redux可以连系其他库一般运用。只不过Redux这类数据管理方式,跟React的数据驱动视图理念很合拍,它俩连系在一起,开辟异常方便。

如今既然有了一个平安的处所存取数据,怎样连系到React内里呢? 我们可以在运用初始化的时刻,竖立一个window.store = createStore(reducer),然后在须要的处所经过过程store.getState()去猎取数据,经过过程store.dispatch去更新数据,经过过程store.subscribe去定阅数据变化然后举行setState…假如许多处所都如许做一遍,实在是不堪其重,而且,照样没有避免掉全局变量的不文雅。

React-Redux

因为全局变量有诸多的瑕玷,那就换个思绪,把store直接集成到React运用的顶层props内里,只需各个子组件能接见到顶层props就好了,比方如许:


<TopWrapComponent store={store}>
 <App />
</TopWrapComponent>,

React正好供应了这么一个钩子,Context,用法很简单,看一下官方demo就清楚明了。如今各个子组件已可以随意马虎地接见到store了,接下来就是子组件把store中用到的数据取出来、修正、以及定阅更新UI等。每个子组件都须要如许做一遍,明显,一定有更方便的要领:高阶组件。经过过程高阶组件把store.getState()、store.dispatch、store.subscribe封装起来,子组件对store就无感知了,子组件一般运用props猎取数据以及一般运用callback触发还调,相当于没有store存在一样。

下面是这个高阶组件的大抵完成:

function connect(mapStateToProps, mapDispatchToProps) {
 return function(WrappedComponent) {
 class Connect extends React.Component {
  componentDidMount() {
  // 组件加载完成后定阅store变化,假如store有变化则更新UI
  this.unsubscribe = this.context.store.subscribe(this.handleStoreChange.bind(this));
  }
  componentWillUnmount() {
  // 组件烧毁后,作废定阅事宜
  this.unsubscribe();
  }
  handleStoreChange() {
  // 更新UI
  this.forceUpdate();
  }
  render() {
  return (
   <WrappedComponent
   {...this.props}
   {...mapStateToProps(this.context.store.getState())} // 参数是store内里的数据
   {...mapDispatchToProps(this.context.store.dispatch)} // 参数是store.dispatch
   />
  );
  }
 }
 Connect.contextTypes = {
  store: PropTypes.object
 };
 return Connect;
 };
}
运用connect的时刻,我们晓得要写一些榜样化的代码,比方mapStateToProps、mapDispatchToProps这两个函数:


const mapStateToProps = state => {
 return {
 count: state.count
 };
};
 
const mapDispatchToProps = dispatch => {
 return {
 dispatch
 };
};
 
export default connect(mapStateToProps, mapDispatchToProps)(Child);
 
// 上述代码实行以后,可以看到connect函数内里的
 <WrappedComponent
 {...this.props}
 {...mapStateToProps(this.context.store.getState())}
 {...mapDispatchToProps(this.context.store.dispatch)}
 />
 
// 就变成了
 <WrappedComponent
 {...this.props}
 {count: store.getState().count}
 {dispatch: store.dispatch}
 />

// 如许,子组件Child的props内里就多了count和dispatch两个属性

// count可以用来衬着UI,dispatch可以用来触发还调

So,如许就OK了?OK了。 经过过程一个闭包天生一个数据中间store,然后把这个store绑定到React的顶层props内里,子组件经过过程HOC竖立与顶层props.store的联络,进而猎取数据、修正数据、更新UI。 这里重要讲了一下三者怎样窜在一起的,假如想相识更高等的功用,比方redux中间件、reducer拆分、connect的其他参数等,可以去看一下对应的源码。

以上就是本文的悉数内容,愿望对人人的进修有所协助,

    原文作者:前端爱好者
    原文地址: https://segmentfault.com/a/1190000017133041
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞