前言
本片介紹 react-redux 中的 provider api,可以通過學習原始碼瞭解設計哲學,從而提高自身。正所謂,不看看原始碼,怎麼敢說你懂呢??
Provider
Provider 是 react-redux 的核心 api 之一,結合 react context api,用於向元件傳遞狀態集。
使用案例
<Provider store={store}>
<APP />
</Provider>
複製程式碼
可見 Provider 也是一個常規的 React 元件,我們向這個元件傳入了 store 屬性,它的值即為呼叫 redux 中 creatStore 方法返回的 store。
./Context
import React from "react";
export const ReactReduxContext = React.createContext(null);
export default ReactReduxContext;
複製程式碼
Provider 原始碼
import React, { Component } from "react";
import PropTypes from "prop-types";
// react context, 可以跨元件層級傳遞狀態。
import { ReactReduxContext } from "./Context";
class Provider extends Component {
// Provider的使用如上例
constructor(props) {
super(props);
const { store } = props;
this.state = {
// storeState為redux建立的狀態集合,呈?樹結構的資料物件
storeState: store.getState(),
store
};
}
componentDidMount() {
this._isMounted = true;
this.subscribe();
}
componentWillUnmount() {
if (this.unsubscribe) this.unsubscribe();
this._isMounted = false;
}
componentDidUpdate(prevProps) {
if (this.props.store !== prevProps.store) {
// 元件更新時,有可能傳入了新的store。
// Provider中訂閱了redux的狀態變化。
if (this.unsubscribe) this.unsubscribe();
this.subscribe();
}
}
subscribe() {
// 訂閱props中store的變化。
const { store } = this.props;
// 使用redux中的subscibe方法訂閱狀態變化。
this.unsubscribe = store.subscribe(() => {
const newStoreState = store.getState();
if (!this._isMounted) {
// 對於provider中資料的更新需要保證元件已經掛載結束。
return;
}
this.setState(providerState => {
// 如果前後兩次狀態未發生變化,則無需進行更新。
if (providerState.storeState === newStoreState) {
return null;
}
return { storeState: newStoreState };
});
});
// 有可能在reder和掛載兩個時間點之間dispatch action,需要考慮此種情況
const postMountStoreState = store.getState();
if (postMountStoreState !== this.state.storeState) {
this.setState({ storeState: postMountStoreState });
}
}
render() {
// context可以傳入,預設使用react context
const Context = this.props.context || ReactReduxContext;
// provider是整個應用的狀態提供者
return (
<Context.Provider value={this.state}>
{this.props.children}
</Context.Provider>
);
}
}
Provider.propTypes = {
store: PropTypes.shape({
subscribe: PropTypes.func.isRequired,
// disptach在其他api中有用
dispatch: PropTypes.func.isRequired,
getState: PropTypes.func.isRequired
}),
context: PropTypes.object,
children: PropTypes.any
};
export default Provider;
複製程式碼
總結
provider api 通過使用 react context 技術,為應用提供通過 redux 生產的狀態集合 store,並在 store 發生更新時,及時更新內部狀態。
注意: context api 需要 react 特定版本的支援。⚠️