0%

React与Redux

Redux

为什么要使用Redux

  • JavaScript开发的应用程序,已经变得越来越复杂了
    • JavaScript需要管理的状态越来越多,越来越复杂
    • 这些状态包括服务器返回的数据、缓存数据、用户操作产生的数据等等,也包括一些UI的状态,比如某些元素是否被选中,是否显示 加载动效,当前分页
  • 管理不断变化的state是非常困难的
    • 状态之间相互会存在依赖,一个状态的变化会引起另一个状态的变化,View页面也有可能会引起状态的变化
    • 当应用程序复杂时,state在什么时候,因为什么原因而发生了变化,发生了怎么样的变化,会变得非常难以控制和追踪
  • React是在视图层帮助我们解决了DOM的渲染过程,但是State依然是留给我们自己来管理
    • 无论是组件定义自己的state,还是组件之间的通信通过props进行传递;也包括通过Context进行数据之间的共享
    • React主要负责帮助我们管理视图,state如何维护最终还是我们自己来决定
  • React主要负责帮助我们管理视图,state如何维护最终还是我们自己来决定
  • Redux除了和React一起使用之外,它也可以和其他界面库一起来使用(比如Vue),并且它非常小(包括依赖在内,只有2kb)

Redux三大原则

  • 单一数据源
    • 整个应用程序的state被存储在一颗object tree中,并且这个object tree只存储在一个 store 中
    • Redux并没有强制让我们不能创建多个Store,但是那样做并不利于数据的维护
    • 单一的数据源可以让整个应用程序的state变得方便维护、追踪、修改
  • State是只读的
    • 唯一修改State的方法一定是触发action,不要试图在其他地方通过任何的方式来修改State
    • 这样就确保了View或网络请求都不能直接修改state,它们只能通过action来描述自己想要如何修改state
    • 这样可以保证所有的修改都被集中化处理,并且按照严格的顺序来执行,所以不需要担心race condition(竟态)的问题
  • 使用纯函数来执行修改、
    • 通过reducer将 旧state和 actions联系在一起,并且返回一个新的State
    • 随着应用程序的复杂度增加,我们可以将reducer拆分成多个小的reducers,分别操作不同state tree的一部分
    • 但是所有的reducer都应该是纯函数,不能产生任何的副作用

Redux项目搭建与使用

  • 安装redux

    1
    npm install redux --save
  • 创建一个对象,作为我们要保存的状态

  • 创建Store来存储这个state

    • 创建store时必须创建reducer

    • 我们可以通过 store.getState 来获取当前的state

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    const { createStore } = require("redux")
    // 初始化数据——要保存的状态
    const initialState = {
    name:"ouwenwu",
    age:22
    }
    // 定义reducer函数:纯函数
    /**
    * 参数1:store中目前报错的state——在createStore时会调用reducer一次,此时参数state为undefined,因此需要为其定义一个初始值,即我们的初始化数据
    * 参数2:传入的action
    * 返回值:返回值会作为store之后存储的state
    */
    function reducer(state=initialState,action){
    console.log("reducer",state,action)
    // 这里使用switch更好
    switch(action.type){
    case "change_name":
    return {...state,name:action.name}
    case "add_age":
    return {...state,age:state.age+action.age}
    default:
    return state
    }
    }

    //创建store
    const store = createStore(reducer)
    module.exports = store
  • 通过action来修改state

    • 通过dispatch来派发action
    • 通常action中都会有type属性,也可以携带其他的数据
  • 修改reducer中的处理代码

    • 这里一定要记住,reducer是一个纯函数,不需要直接修改state
    • 后面我会讲到直接修改state带来的问题
  • 可以在派发action之前,监听store的变化

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    const store=require("./store");

    // 开启store订阅——这个订阅是在派发action之前订阅的,会在store所监听的state修改时调用
    const unsubscribe = store.subscribe(()=>{
    console.log("订阅数据发生变化",store.getState())
    })

    // actionFunction——将action抽取为函数,那么后面每次需要创建action不用手动编写,调用函数生成
    const changeNameAction = (name)=>({
    type:"change_name",
    name
    })
    const addAgeAction = (age)=>({
    type:"add_age",
    age
    })
    // 修改store中的数据:必须action——手动写action
    const nameAction ={type:"change_name",name:"kobe"}
    store.dispatch(nameAction)
    store.dispatch(changeNameAction("kebi1"))
    // 取消订阅
    unsubscribe()
    store.dispatch({type:"add_age",age:1})
    store.dispatch(addAgeAction(1))

    输出image-20230330092932419

Redux项目抽取

如果我们将所有的逻辑代码写到一起,那么当redux变得复杂时代码就难以维护

  • store/index.js文件——利用reducer创建store

    1
    2
    3
    4
    import {createStore} from "redux"
    import reducer from "./reducer"
    //创建store
    export const store = createStore(reducer)
  • store/reducer.js文件——reducer函数和state默认值\

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    import * as actionType from "./constants.js"

    const initialState = {
    name:"ouwenwu",
    age:22
    }
    // 定义reducer函数:纯函数
    /**
    * 参数1:store中目前报错的state
    * 参数2:传入的action
    * 返回值:返回值会作为store之后存储的state
    */
    function reducer(state=initialState,action){
    console.log("reducer",state,action)
    // 这里使用switch更好
    switch(action.type){
    case actionType.CHANGE_NAME:
    return {...state,name:action.name}
    case actionType.ADD_AGE:
    return {...state,age:state.age+action.age}
    default:
    return state
    }
    }
    export default reducer
  • store/actionCreator.js文件——将store要派发的action,抽取成函数放在此处

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import * as actionType from "./constants.js"

    export const changeNameAction = (name)=>({
    type:actionType.CHANGE_NAME,
    name
    })
    export const addNameAge = (age)=>({
    type:actionType.ADD_AGE,
    age
    })
  • store/constants.js文件——常量文件,将action中的type抽取出来

    1
    2
    export const CHANGE_NAME = "change_name"
    export const ADD_AGE = "add_age"

Redux与React融合

image-20230330102727040

redux配置代码如上所述

jsx代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import React from "react";
import store from "./store/index.js"
import { changeNameAction, addAgeAction } from "./store/actionCreator";
//编写组件
class App extends React.PureComponent{
constructor(){
super()
// 初始化值使用store中的初始化变量
this.state = {
name:store.getState().name,
age:store.getState().age
}
}
// 加载页面前订阅store,使得其更改时调用对应的函数改变state引起页面的刷新
componentDidMount(){
this.unsubScribe = store.subscribe(()=>{
const state = store.getState()
this.setState({
name:state.name,
age:state.age
})
})
}
// 页面卸载前取消订阅
componentWillUnmount(){
this.unsubScribe()
}
changeName(){
store.dispatch(changeNameAction("www"))
}
addAge(){
store.dispatch(addAgeAction(1))
}
render(){
const {name,age} = this.state
return (
<div>
<button onClick={()=>{this.changeName()}}>改变名字</button>
<button onClick={()=>{this.addAge()}}>age+1</button>
<div>
<h2>{name}</h2>
<h3>{age}</h3>
</div>
</div>
)
}
}
export default App

react-redux的使用

  • index.js(整个react的入口):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    import React from "react";
    import ReactDOM from "react-dom/client";
    import App from "./App"
    import { Provider } from "react-redux";
    import store from "./store";



    // 编写REACT代码,通过REACT渲染内容
    /**
    * 这里的Provider实际上是基于Context实现的,用它包裹App及其子组件可以使用传入的stero
    * stero在底层是通过value实现的
    */
    const root = ReactDOM.createRoot(document.querySelector('#root'))
    root.render(
    <Provider store={store}>
    <App/>
    </Provider>
    )
  • App.js代码(获取stero并使用代码):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    import React from "react";
    import { connect } from "react-redux";
    import { addAgeAction } from "./store/actionCreator";
    //编写组件
    class App extends React.PureComponent{
    constructor(){
    super()
    }
    addAgeByButton(){
    // store.dispatch(addAgeAction(1))
    this.props.addAge(1)
    }
    render(){
    return (
    <div>
    <button onClick={()=>{this.addAgeByButton()}}>age+1</button>
    <div>
    <h3>{this.props.age}</h3>
    </div>
    </div>
    )
    }
    }
    // 相当于添加监听,会把stero中的state中的对应属性添加到props中
    function mapStateToProps(state){
    // 需要用哪些就使用哪些,会将这个返回对象和本来的props合并
    return{
    age:state.age
    }
    }
    // 设置dispatch,会把return中的函数放到this.pros中去,通过调用这个函数可以发送action给stero
    const mapDispatchToProps = (dispatch)=>{
    return{
    addAge(age){
    dispatch(addAgeAction(age))
    }
    }
    }
    // connect()返回值是一个高阶函数
    /**
    * connect()参数1:store中的哪些数据需要映射到这个组件的props——函数
    * connect()参数2:
    */
    export default connect(mapStateToProps,mapDispatchToProps)(App)
  • stero的代码,index.js/constants.js/actionCreate.js/reducer.js依然像上方写的一样

redux异步处理

react获取网络请求:

  • componentDidMount中发起网络请求,并在结束后赋值给state

    • 这种方式数据管理和react耦合性高,和redux的要求不符
  • 通过redux获取网络请求,由jsx组件中发起action,在action中获取数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    /**
    * 由于网络请求通常是异步的,函数的return中不能直接获得网络请求的值,因此普通的action是不能实现异步的
    */
    export const netWorkAction = ()=>{
    new Promise((resolve, reject) => {
    setTimeout(()=>{
    resolve("oww")
    },5000)
    }).then(res=>{
    return{
    type:actionType.CHANGE_NAME,
    name:res
    }
    })
    return {}
    }

    redux-thunk中间件技术

    • 安装redux-thunk

      1
      npm install react-thunk --save
    • 设置react可以使用thunk,thunk允许dispatch一个函数,之后会自动执行这个函数

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      import { applyMiddleware, combineReducers, createStore } from "redux";
      import countReducer from "./countStore/reducer";
      import homeReducer from "./homeStore/reducer";
      import thunk from "redux-thunk";
      const reducer = combineReducers({
      age:countReducer,
      name:homeReducer
      })

      // combineReducers的底层实现
      function reducerByUs(state = {}, action){
      return {
      /**
      * 第一次执行时(createStore),传入undefined,得到的是默认值对象
      * 后续执行时,每次传入上次的state,得到正确值
      */
      age:countReducer(state.age, action),
      name:homeReducer(state.name,action)
      }
      }
      // 包裹中间件
      export const store = createStore(reducer,applyMiddleware(thunk))
      export default store

      action代码

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      export const netWorkAction = ()=>{
      console.log("dispatch foo")
      const foo = (dispatch, getState)=>{
      new Promise((resolve) => {
      setTimeout(()=>{
      resolve("oww")
      },5000)
      }).then(res=>{
      dispatch(changeNameAction(res))
      })
      }
      return foo
      }

      jsx中发起dispatch代码

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      import React from "react";
      import { connect } from "react-redux";
      import { addAgeAction } from "./store/countStore";
      import { netWorkAction } from "./store/homeStore";
      //编写组件
      class App extends React.PureComponent{
      constructor(){
      super()
      }
      addAgeByButton(){
      // store.dispatch(addAgeAction(1))
      this.props.addAge(1)
      this.props.changeName()
      }

      render(){
      return (
      <div>
      <button onClick={()=>{this.addAgeByButton()}}>changeinfo</button>
      <div>
      <h2>{this.props.name}</h2>
      <h3>{this.props.age}</h3>
      </div>
      </div>
      )
      }
      }

      // 相当于添加监听,会把stero中的state中的对应属性添加到props中
      function mapStateToProps(state){
      // 需要用哪些就使用哪些,会将这个返回对象和本来的props合并
      return{
      age:state.age.age,
      name:state.name.name
      }
      }
      // 设置dispatch,会把return中的函数放到this.pros中去,通过调用这个函数可以发送action给stero
      const mapDispatchToProps = (dispatch)=>{
      return{
      addAge(age){
      dispatch(addAgeAction(age))
      },
      changeName(){
      dispatch(netWorkAction())
      }
      }
      }
      // connect()返回值是一个高阶函数
      /**
      * connect()参数1:store中的哪些数据需要映射到这个组件的props——函数
      * connect()参数2:
      */
      export default connect(mapStateToProps,mapDispatchToProps)(App)

redux代码拆分

不拆分的reducer:

  • 一个reducer处理多个页面的数据
  • 将所有状态都放到reducer中进行管理,随着项目的日趋庞大,会造成代码臃肿

对reducer进行拆分:

  • 将对不同页面的数据或造成抽取为不同的reducer
  • 将多个reducer合并为一个

combineReducers函数

事实上,redux给我们提供了一个combineReducers函数可以方便的让我们对多个reducer进行合并

页面一store代码:

  • actionCreator.js

    1
    2
    3
    4
    5
    6
    import * as actionType from "./constants.js"

    export const changeNameAction = (name)=>({
    type:actionType.CHANGE_NAME,
    name
    })
  • constants.js

    1
    export const CHANGE_NAME = "change_name"
  • index.js

    1
    2
    3
    4
    5
    6
    import homeReducer from "./reducer"

    // 统一当初当前模块的数据
    export default homeReducer
    export * from "./actionCreator"
    export * from "./constants"
  • reducer.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    import * as actionType from "./constants.js"

    const initialState = {
    name:"ouwenwu",
    age:22
    }
    // 定义reducer函数:纯函数
    /**
    * 参数1:store中目前报错的state
    * 参数2:传入的action
    * 返回值:返回值会作为store之后存储的state
    */
    function homeReducer(state=initialState,action){
    console.log("reducer",state,action)
    // 这里使用switch更好
    switch(action.type){
    case actionType.CHANGE_NAME:
    return {...state,name:action.name}
    default:
    return state
    }
    }
    export default homeReducer

页面一store代码:

  • actionCreator.js

    1
    2
    3
    4
    5
    6
    import * as actionType from "./constants.js"

    export const changeNameAction = (name)=>({
    type:actionType.CHANGE_NAME,
    name
    })
  • constants.js

    1
    export const CHANGE_NAME = "change_name"
  • index.js

    1
    2
    3
    4
    5
    6
    import homeReducer from "./reducer"

    // 统一当初当前模块的数据
    export default homeReducer
    export * from "./actionCreator"
    export * from "./constants"
  • reducer.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    import * as actionType from "./constants.js"

    const initialState = {
    name:"ouwenwu",
    age:22
    }
    // 定义reducer函数:纯函数
    /**
    * 参数1:store中目前报错的state
    * 参数2:传入的action
    * 返回值:返回值会作为store之后存储的state
    */
    function homeReducer(state=initialState,action){
    console.log("reducer",state,action)
    // 这里使用switch更好
    switch(action.type){
    case actionType.CHANGE_NAME:
    return {...state,name:action.name}
    default:
    return state
    }
    }
    export default homeReducer

页面二store代码:

  • actionCreator.js

    1
    2
    3
    4
    5
    6
    import * as actionType from "./constants.js"

    export const addAgeAction = (age)=>({
    type:actionType.ADD_AGE,
    age
    })
  • constants.js

    1
    export const ADD_AGE = "add_age"
  • index.js

    1
    2
    3
    4
    5
    import countReducer from "./reducer"

    export default countReducer
    export * from "./actionCreator"
    export * from "./constants"
  • reducer.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    import * as actionType from "./constants.js"

    const initialState = {
    age:22
    }
    // 定义reducer函数:纯函数
    /**
    * 参数1:store中目前报错的state
    * 参数2:传入的action
    * 返回值:返回值会作为store之后存储的state
    */
    function countReducer(state=initialState,action){
    console.log("reducer",state,action)
    // 这里使用switch更好
    switch(action.type){
    case actionType.ADD_AGE:
    console.log(state.age,action.age)
    return {...state,age:state.age+action.age}
    default:
    return state
    }
    }
    export default countReducer

合并两个store的代码:

index.js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { combineReducers, createStore } from "redux";
import countReducer from "./countStore/reducer";
import homeReducer from "./homeStore/reducer";

const reducer = combineReducers({
age:countReducer,
name:homeReducer
})

// combineReducers的底层实现
function reducerByUs(state = {}, action){
return {
/**
* 第一次执行时(createStore),传入undefined,得到的是默认值对象
* 后续执行时,每次传入上次的state,得到正确值
*/
age:countReducer(state.age, action),
name:homeReducer(state.name,action)
}
}
export const store = createStore(reducer)
export default store

合并数据的使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import React from "react";
import { connect } from "react-redux";
import { addAgeAction } from "./store/countStore";
//编写组件
class App extends React.PureComponent{
constructor(){
super()
}
addAgeByButton(){
// store.dispatch(addAgeAction(1))
this.props.addAge(1)
}
render(){
return (
<div>
<button onClick={()=>{this.addAgeByButton()}}>age+1</button>
<div>
<h3>{this.props.age}</h3>
</div>
</div>
)
}
}
// 相当于添加监听,会把stero中的state中的对应属性添加到props中
function mapStateToProps(state){
// 需要用哪些就使用哪些,会将这个返回对象和本来的props合并
return{
// 这里获取到的stero为合并后的state,而合并后的state.age是一个reducer对象,因此要再加一个.age才能获取到真实值
age:state.age.age
}
}
// 设置dispatch,会把return中的函数放到this.pros中去,通过调用这个函数可以发送action给stero
const mapDispatchToProps = (dispatch)=>{
return{
addAge(age){
dispatch(addAgeAction(age))
}
}
}
// connect()返回值是一个高阶函数
/**
* connect()参数1:store中的哪些数据需要映射到这个组件的props——函数
* connect()参数2:
*/
export default connect(mapStateToProps,mapDispatchToProps)(App)

ReduxToolkit的使用(RTK)

  • 安装

    1
    npm install @reduxjs/toolkit react-redux
  • Redux Toolkit包旨在成为编写Redux逻辑的标准方式,从而解决上面提到的问题

Redux Toolkit的核心API主要是如下几个:

  • configureStore:包装createStore以提供简化的配置选项和良好的默认值。它可以自动组合你的 slice reducer,添加你提供 的任何 Redux 中间件,redux-thunk默认包含,并启用 Redux DevTools Extension

  • createSlice:接受reducer函数的对象、切片名称和初始状态值,并自动生成切片reducer,并带有相应的actions

  • createAsyncThunk: 接受一个动作类型字符串和一个返回承诺的函数,并生成一个pending/fulfilled/rejected基于该承诺分 派动作类型的 thunk

createSlice代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import { createSlice } from "@reduxjs/toolkit";
import { createAsyncThunk } from "@reduxjs/toolkit";
// @reduxjs/toolkit的异步操作1
/**
* payload是在jsx中dispatch时传入的额外参数
*/
export const getNameAction1 = createAsyncThunk("age/changeName",async(payload, stero)=>{
const {dispatch, getState} = stero
new Promise((resolve)=>{
setTimeout(()=>{
resolve("ouwenwu")
},5000)
}).then(res=>[
dispatch(changeName(res))
])
})
// @reduxjs/toolkit的异步操作2
export const getNameAction = createAsyncThunk("age/changeName",async(payload, stero)=>{
const {dispatch, getState} = stero
const res = await new Promise((resolve)=>{
setTimeout(()=>{
resolve("ouwenwu")
},2000)
})
console.log(res)
return res
})
const ageSlice = createSlice({
name:"ageSlice", // 用户后面标记当前操作类型,与react中action的type类似——但是不再需要写出来各种type,而自动实现
// 初始值
initialState:{
name:"oww",
age:22
},
// 相当于之前的reducer函数,可以添加很多的函数,每一个函数都相当于一个原来的case
reducers:{
addAge(state, action){
state.age += action.payload
console.log(action)
},
subAge(state, action){
state.age -= action.payload
console.log(action)
},
changeName(state,action){
state.name = action.payload
console.log(action)
}
},
// 监听异步dispatch
extraReducers:{
/**
* getNameAction一个有三个状态
* pending:action被发出,但是还没有最终的结果
* fulfilled:获取到最终的结果(有返回值的结果)
* rejected:执行过程中有错误或者抛出了异常
*/
[getNameAction.fulfilled](state, action){
state.name = action.payload
console.log(action)
}
}
})
// createSlice是一个把参数穿进去,返回一个对象,包含之前的reducer、action等,使用方法和之前使用相同
export const {addAge, subAge, changeName} = ageSlice.actions
const ageReucer = ageSlice.reducer
export default ageReucer

configureStore代码

1
2
3
4
5
6
7
8
9
10
import { configureStore } from "@reduxjs/toolkit"
import ageReucer from "./countStore/ageSlice"


const store = configureStore({
reducer:{
age: ageReucer
}
})
export default store

jsx代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import React from "react";
import { connect } from "react-redux";
import { addAge, subAge, getNameAction } from "./store/countStore/ageSlice";
//编写组件
class App extends React.PureComponent{
constructor(){
super()
}
addAgeByButton(){
this.props.addAge(1)
}
subAgeByButton(){
this.props.subAge(1)
}
changeNameByButton(){
this.props.changeName()
}
render(){
return (
<div>
<button onClick={()=>{this.addAgeByButton()}}>addAge</button>
<button onClick={()=>{this.subAgeByButton()}}>subAge</button>
<button onClick={()=>{this.changeNameByButton()}}>changeName</button>
<div>
<h2>{this.props.name}</h2>
<h3>{this.props.age}</h3>
</div>
</div>
)
}
}

// 相当于添加监听,会把stero中的state中的对应属性添加到props中
function mapStateToProps(state){
// 需要用哪些就使用哪些,会将这个返回对象和本来的props合并
return{
name:state.age.name,
age:state.age.age
}
}
// 设置dispatch,会把return中的函数放到this.pros中去,通过调用这个函数可以发送action给stero
const mapDispatchToProps = (dispatch)=>{
return{
addAge(age){
dispatch(addAge(age))
},
subAge(age){
dispatch(subAge(age))
},
changeName(){
dispatch(getNameAction("aaa"))
}
}
}
// connect()返回值是一个高阶函数
/**
* connect()参数1:store中的哪些数据需要映射到这个组件的props——函数
* connect()参数2:
*/
export default connect(mapStateToProps,mapDispatchToProps)(App)