- React-Redux 是为了方便在 React 项目中使用 Redux 所封装的库
- React-Redux 把组件分为两类:UI 组件(Component)和容器组件(Container)
- React-Redux 提供 Provider 组件,使它的子组件(容器组件)都能拿到 state
UI 组件特征:
- 只负责 UI 的呈现,不带有任何业务逻辑
- 没有状态(this.state)
- 所有数据都由组件属性(this.props)提供
- 不使用任何 Redux 的 API
UI 组件示例:
const Title = value => <h1>{value}</h1>;
容器组件(逻辑组件)
容器组件特征:
- 负责管理数据和业务逻辑,不负责 UI 的呈现
- 带有内部状态
- 通过 Redux 的 API 生成
如果一个组件既有 UI 呈现又有业务逻辑,则将它封装为如下结构:
- 外面是一个容器组件,里面包裹一个UI 组件
- 容器组件负责与外部的通信,将数据传给 UI 组件
- UI 组件接受数据,并渲染出视图
由 UI 组件生成容器组件,需要三个要素:
- 连接通信 - 连接 UI 组件和容器组件,为输入输出 state 做准备
- 逻辑输入 - 将容器组件的 state 映射为 UI 组件的 props
- 逻辑输出 - 用户动作触发 UI 组件绑定事件,dispatch 更新容器组件 state
容器组件的三要素对应 React-Redux 的 API:
- 连接通信 - connect
- 逻辑输入 - mapStateToProps
- 逻辑输出 - mapDispatchToProps
其中,mapStateToProps 和 mapDispatchToProps 作为 connect 的参数传入
1. connect() 示例:
import {connect} from 'react-redux';
const Container = connect(
mapStateToProps,
mapDispatchToProps
)(Component);
2. mapStateToProps() 示例:
const mapStateToProps = (state, ownProps) => {
return props;
};
mapStateToProps 会订阅 Store,每当 state 更新,就会自动执行,重新计算 UI 组件的 props,从而触发 UI 组件的重新渲染
3. mapDispatchToProps 示例:
3.1 mapDispatchToProps 函数:
const mapDispatchToProps = (dispatch, ownProps) => {
return {
handleClick: () => {
dispatch(action);
}
};
};
3.2 mapDispatchToProps 对象:
const mapDispatchToProps = {
handleClick: actionCreator;
};
mapDispatchToProps 用来建立 UI 组件的 props 到 Store.dispatch 方法的映射
至此,容器组件与内部的 UI 组件的通信已经解决。容器组件还需要与外部通信,拿到 state 对象。
React-Redux 提供 Provider 组件,可以让容器组件拿到 state。
4. Provider 示例:
import {Provider} from 'react-redux';
import {createStore} from 'redux';
import todoApp from './reducers';
import App from './components/App';
const store = createStore(todoApp);
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
React-Redux 综合实例:Provider 在【根组件】App 外面包了一层。这样,所有子组件就可以拿到 state 了
实现步骤:
- 定义 UI 组件。规划组件属性 this.props,组件属性包括【展示属性】和【绑定事件】
- 定义组件通信。包括【展示数据】到 state 的映射、【绑定事件】到 dispatch 的映射
- 将 UI 组件包装成容器组件
- 定义容器组件的 Reducer
- 生成 Store 对象,并使用 Provider 在根组件外面包一层
流程概括如下:
Component
- [mapDispatchToProps/mapDispatchToProps] -
=> Container
- [connect] -
- [Reducer] -
=> Store + Provider
计数器(Counter)示例:
-
导入所需组件(确保依赖已安装)
import React, {Component} from 'react'; import PropTypes from 'prop-types'; import ReactDOM from 'react-dom'; import {createStore} from 'redux'; import {Provider, connect} from 'react-redux';
-
定义 UI 组件
class Counter extends Component { render() { const {value, onIncreaseClick} = this.props return ( <div> <span>{value}</span> <button onClick={onIncreaseClick}>Increase</button> </div> ); } } Counter.propTypes = { value: PropTypes.number.isRequired, onIncreaseClick: PropTypes.func.isRequired };
-
定义组件通信
// Action Creator const increaseAction = { type: 'increase' }; const mapStateToProps = state => { return {value: state.count} }; const mapDispatchToProps = dispatch => { return { onIncreaseClick: () => dispatch(increaseAction); } };
-
包装容器组件
const App = connect( mapStateToProps, mapDispatchToProps )(Counter);
-
定义 Reducer
function counter(state = {count: 0}, action) { const count = state.count; switch (action.type) { case 'increase': return { count: count + 1 }; default: return state; } }
-
生成 Store 对象
const store = createStore(counter) ReactDOM.render( <Provider store={store}> <App/> </Provider>, document.getElementById('root') );
Tips: 本文总结自阮一峰老师的文章 React-Redux 的用法,如果对您有帮助,可以给阮一峰老师留言感谢 !