Redux组成
- state
存放redux属性 - action
一个对象, 必须包含type属性 - reducer
根据传入的action更改state的值 - store
提供getState()方法获取state
提供dispatch()方法发送action
通过subscribe()注册监听
通过subscribe()的返回值注销监听
react-redux
增加Provider
和connect
两个重要部分
- Provider
被<Provider>包围的所有组件中都可以获取store中的数据
<Provider store={store}>
<App></App>
</Provider>
- connect
作用: 将组件和store关联
Provider内部的组件如果想使用state中的数据, 必须将组件用connect进行一层封装
connect(p1,p2,...)(component组件)
第一个括号返回一个函数, 这个函数的入参是要包装的组件, 返回值是被connect增强的新的组件
connect入参:
funciton mapStateToProps(state,ownProps)
作用:将store中的数据作为props绑定到组件上
state:
redux中的store ownProps:
自己的props
function mapDispatchToProps(dispatch,ownProps)
作用:将action作为props绑定到自己的函数中
dispatch:
store.dispatch() ownProps:
自己的props
一个react-redux的基本流程
- 创建一个reducer
const reducer = (state=defaultState, action)=>{switch(action.type) .code.. return {...state}}
- 创建一个reducer
- 创建一个store对象
import {createStore} from 'redux'
const store = createStore(reducer)
- 创建一个store对象
- 将APP组件包装进Provider, 并传入store
import {Provider} from 'react-redux'
<Provider store={store}> <App/> </Provider>
- 将APP组件包装进Provider, 并传入store
- 使用connect加强组件
import {connect} from 'react-redux'
export default connect(mapStateToProps, mapDispatchToProps,...)(MyComponent)
- 使用connect加强组件
- 使用redux进行状态管理的组件, 可以分为发送方和接收方. (也可以同时是两者)
接收方: 实现mapStateToProps
发送方: 实现mapDispatchToProps
- 使用redux进行状态管理的组件, 可以分为发送方和接收方. (也可以同时是两者)
mapStateToProps
作为connect的第一个参数传入, 作用是将store.state的指定属性传入组件的props中.
const mapStateToProps = (state)=>{
return {
myNumber:state.number
}
}
export default connect(mapStateToProps)(comB)
// 通过connect的加强, comB组件的props中多了一个myNumber的属性
// 通过this.props.myNumber的调用, 可以访问到store.state.number这个属性
// 当store的reducer更改了state.number的时候, 组件中引用this.props.myNumber的UI也会刷新
-
mapDispatchToProps
作为connect的第二个参数传入, 作用是将执行store.dispath(action)
的方法传入组件的props中. 例如:
const mapDispatchToProps = (dispatch)=>{
return {
addClicked:()=>{
dispatch({
type:"action_add"
})
}
}
}
export default connect(null,mapDispatchToProps)(comA)
// 通过connect的加强, comA组件的props中多了一个addClicked的方法
// 通过this.props.addClicked()的调用, 会执行store.dispatch(action)
// 执行后会发送action, 从而是store的reducer执行, 更新state, 进而更新UI
项目讲解
[addButton] [100]
页面效果如上, 按钮部分定义为组件comA, 显示数字的部分定义为组件comB. 页面显示在组件APP上.
工程组成:
-<store>
--index.jsx
-<reducer>
--index.jsx
-comA.jsx
-comB.jsx
-app.jsx
/*
reducer / index.jsx
*/
const defaultState = {
number:100
}
exports.reducer = (state=defaultState, action)=>{
console.log('reducer run',action.type);
switch (action.type) {
case 'action_add':
return {number:state.number+1}
default:
break;
}
return state;
}
/*
store / index.jsx
*/
import {createStore} from 'redux'
import {reducer} from '../reducer'
export default createStore(reducer)
/*
index.jsx
*/
import React from 'react'
import ReactDOM from 'react-dom'
import {Provider} from 'react-redux'
import ComA from './ComA'
import ComB from './ComB'
import store from './store';
class App extends React.Component{
render(){
return <Provider store={store}>
<ComA/>
<ComB/>
</Provider>
}
}
ReactDOM.render(<App />, document.getElementById('root'));
/*
store创建需要传入reducer
将<APP>组件封装到<Provider>中, 将store作为Provider的属性传入.
这样整个<APP>组件及其子组件都可以访问到store
*/
/*
comA.jsx
*/
import React from 'react'
import {connect} from 'react-redux'
class comA extends React.Component{
render(){
return <div>
<input type='button' value=' + ' onClick={this.add}></input>
</div>
}
add = ()=>{
console.log("button clicked",this.props)
this.props.addClicked()
}
}
// 发送方 需要实现 connect 的第二个参数 mapDispatchToProps
// 入参是传入的store.dispatch
// 返回值是一个对象, 该对象的key是将要传入的组件中的props的方法, value传一个箭头函数, 函数中调用dispatch()
// dispatch()的入参是一个action对象, action对象一定要有type属性
// 该方法会将addClicked方法注入到组件的props中去, 组件中执行this.props.addClicked(), 相当于执行了store.dispatch(action)
// 每当store.dispatch(action)执行时, store 而这个action的type就是action_add.
const mapDispatchToProps = (dispatch)=>{
return {
addClicked:()=>{
dispatch({
type:"action_add"
})
}
}
}
export default connect(null,mapDispatchToProps)(comA)
/*
comB.jsx
*/
import React from 'react'
import {connect} from 'react-redux'
class comB extends React.Component{
render(){
return <div>
<p>{this.props.myNumber}</p>
</div>
}
}
// 接收方 需要实现connect的第一个参数 mapStateToProps
// 入参是store.state 返回值是一个对象, key是注入到组件的props中的属性名, value可以从state中取
// 注入后可以再组件中的props中方为到state的属性了
const mapStateToProps = (state)=>{
return {
myNumber:state.number
}
}
export default connect(mapStateToProps)(comB)