本文引见了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的其他参数等,可以去看一下对应的源码。
以上就是本文的悉数内容,愿望对人人的进修有所协助,