react-redux把组件分为UI组件和容器组件。先看图下图:
下面让咱们带着问题学习一下react-redux:
1. react-redux如何将store分发到不一样组件中?
2. react-redux如何作到store发生变化, 对应的组件从新render, 也就是说如何subscribe store?html
用于包裹UI组件生成容器组件, 也就是connect链接的意思。
connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options]); // mapStateToProps(state, ownProps?): function, 返回的是Object(stateProps), 该方法将容器组件state映射到UI组件的props, 也就是输入逻辑, 重点是mapStateToProps会订阅store,每当store更新时, 会从新执行, 若是计算出的UI组件的参数发生变化, 就会触发UI组件的从新渲染。state, 表明监听的全局store,也能够说是全局的state, ownProps表示该组件自身携带的props方法。 // mapDispatchToProps(dispatch, [ownProps]):function/Object, 若是返回的是对象,则对应每一个Action 的函数名, 在UI组件中调用须要dispatch, 若是返回的是函数,则已经被dispatch包裹(能够用bindActionCreators)。 该参数主要是映射用户动做Action, 从UI组件传递出去, 也就是输出逻辑,这里能够用到redux的api bindActionCreators, // mergeProps(stateProps, dispatchProps, ownProps) 指定传入的UI组件的props, 默认是Object.assign({}, ownProps, stateProps, dispatchProps) // options: Obejct, 能够进一步定义connect功能, 如定义store的来源,指定props的一些更新规则等。 // action,js ... export const initSelectConcact = (streamConcacts: StreamToConcact): InitSelectConcactAction => ({ type: LOCAL_CONCACT, streamConcacts, }); export const testFetch = (dispatch) => dispatch(initSelectConcact([])); // UnreadCards.js class UnreadCards ... componentDidMount() { this.props.fetchStreamConcact(); } const mapStateToProps = (state, ownProps) => ({ users: getUsers(state), }); const mapDispatchToProps = (dispatch, ownProps) => ({ fetchStreamConcact: () => testFetch(dispatch), // 或者以下 fetchStream: bindActionCreators(initSelectConcact, dispatch) }); const mergeProps = (stateProps, dispatchProps, ownProps) => { console.log('mergeProps', stateProps, dispatchProps, ownProps); return Object.assign({}, ownProps, { todos: stateProps.todos[ownProps.userId], addTodo: (text) => dispatchProps.addTodo(ownProps.userId, text), }); }; const options = { pure: true, storeKey: 'store', }; export default connect(mapStateToProps, mapDispatchToProps, mergeProps, options)(UnreadCards);
connect
生成容器组件后,须要将是state数据传递到子组件中, 有两种方案:react
A -> B -> C
组件数据中传递, 能够经过props一层层的传递。A -> B -> C
利用React 的 context属性, 将state绑在跟组件A的context中, A下面的全部子组件均可以经过context拿到是state。为避免在connect参数mapDispatchToProps
中反复写action, 我将全部Action经过方法绑定在props的actions上, 不用每次去映射当前页面所需的action。redux
import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; // 全部页面action集合 import * as actions from './actions'; // 缓存actions, 不用每次render都从新加载 let cachedActions; // action经过bindActionCreators绑定dispatch, const bindActions = (dispatch, ownProps) => { if (!cachedActions) { cachedActions = { dispatch, actions: bindActionCreators(actions, dispatch), }; } return cachedActions; }; const connectWithActions = (mapStateToProps: MapStateToProps, mergeProps, options) => ( component, ) => connect(mapStateToProps, bindActions, mergeProps, options)(component); export default connectWithActions; // 用法 class HomeScreen extennds Component { componentWillMount() { this.props.actions.getList(); } ... } export default connectWithActions(state => ({ users: state.users, }))(HomeScreen);
-----完-----api
参考文章缓存