React:快速上手(5)——掌握Redux(2)
本文部分内容参考阮一峰的Redux教程。
React-Redux原理
React-Redux运行机制
我觉得这张图清楚地描述React-Redux的运行机制:
React-Redux将组件划分为两类,第一类是UI组件:
- 只负责 UI 的呈现,不带有任何业务逻辑
- 没有状态(即不使用
this.state
这个变量) - 所有数据都由参数(
this.props
)提供 - 不使用任何 Redux 的 API
比如,我们的实例计数器就是一个UI组件,我们只写了UI的呈现规则,并且所有数据都是由this.props提供:
class Counter extends React.Component{render() {
const{onSubmitClick,value} = this.props;
return(
<div>
<span>{value}</span>
<button onClick={onSubmitClick}>提交</button>
</div>
)
}
}
第二类组件是容器组件:
- 负责管理数据和业务逻辑,不负责 UI 的呈现
- 带有内部状态
- 使用 Redux 的 API
不过,React-Redux 规定,所有的 UI 组件都由用户提供,容器组件则是由 React-Redux 自动生成。
Connect负责从UI组件生成容器组件
如下,一行语句,我们就将获得由UI组件得到的容器组件
const CounterApp = connect(mapStateToProps,mapDispatchToProps)(Counter)
这个函数由两个参数,mapStateToProps和mapDispatchToProps构成。它们主要定义业务逻辑,前者负责输入逻辑,即容器组件如何将state转换为props交给UI组件,来供容器组件进行UI渲染。后者负责输出逻辑,用来建立 UI 组件的参数到store.dispatch
方法的映射。
如下,我们定义mapStateToProps,它将state中的count字段取出映射到value属性,然后交给UI组件:
function mapStateToProps(state) {return{
value:state.count
}
}
然后,我们定义mapDispatchToProps,他将store.dispatch方法映射到onSubmitClick属性上,这样UI组件通过props.onSubmitClick,就可以间接调用store.dispatch,实现状态更新。
function mapDispatchToProps(dispatch) {return{
onSubmitClick:()=>dispatch({type:'INCREASE'})
}
}
<Provider>组件
connect
方法生成容器组件以后,需要让容器组件拿到state
对象,才能生成 UI 组件的参数。一种解决方法是将state
对象作为参数,传入容器组件。但是,这样做比较麻烦,尤其是容器组件可能在很深的层级,一级级将state
传下去就很麻烦。
React-Redux 提供Provider
组件,可以让容器组件拿到state
。
import { Provider } from 'react-redux'import { createStore } from 'redux'
import todoApp from './reducers'
import App from './components/App'
let store = createStore(todoApp);
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
上面代码中,Provider
在根组件外面包了一层,这样一来,App
的所有子组件就默认都可以拿到state
了。
一个完整的计数器例子
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'
// React component
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
const increaseAction = { type: 'increase' }
// 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)
// Map Redux state to component props
function mapStateToProps(state) {
return {
value: state.count
}
}
// Map Redux actions to component props
function mapDispatchToProps(dispatch) {
return {
onIncreaseClick: () => dispatch(increaseAction)
}
}
// Connected Component
const App = connect(
mapStateToProps,
mapDispatchToProps
)(Counter)
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
以上是 React:快速上手(5)——掌握Redux(2) 的全部内容, 来源链接: utcz.com/z/382492.html