我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

本文接着分析create-react-appredux范例,reducer整合到了redux/toolkitslice内。本文则侧重于这些函数如何调用,也就是dispatch的概念。react-redux提供了个useDispatch()的概念,就是用来干这个事情的。

苏南大叔:create-react-app的redux范例,如何通过dispatch修改state? - redux-dispatch-state
create-react-app的redux范例,如何通过dispatch修改state?(图5-1)

大家好,这里是苏南大叔的程序如此灵动博客,这里记录苏南大叔的代码故事。本文描述reactredux结合后,如何调用定义在reducer里面的函数修改state的故事。测试环境:win10node@16.14.2create-react-app@5.0.1reduxjs/toolkit@1.8.3react-redux@8.0.2

useSelector读取只读state

react-redux中使用useState()来获得redux中的state的数据,并且相关函数里面是无法修改state的数据的,会提示无法扩展或者只读。相关文章:

const selectCount = (state) => state.store_reducer_name.value;
const count = useSelector(selectCount);

翻译过来是这样的:

const count = state.store_reducer_name.value;

reducer修改state

想修改state中的数据,使用的概念是定义在slice中的reducers里面函数,修改state数据。

export const counterSlice = createSlice({
  name: 'counter_slice_name',
  initialState :{
    value: 0,
    status: 'idle',
  },
  reducers: {
    decrement: (state) => {
      state.value -= 1;
    },
    incrementByAmount: (state, action) => {
      state.value += action.payload;
    },
  },
});

苏南大叔:create-react-app的redux范例,如何通过dispatch修改state? - 定义actions
create-react-app的redux范例,如何通过dispatch修改state?(图5-2)

这里的核心范例代码,如下:

decrement: (state) => {
  state.value -= 1;
},
incrementByAmount: (state, action) => {
  state.value += action.payload;
},

重点就是action.payload,就是传递过来的参数,可以是任何类型。比如:数组、字符串、数字、object等。

dispatch执行reducer转变的action

这里首先有个useDispatch,来自react-redux。使用了之后,就可以在react组件里面调用相关的reducer函数了。
范例如下:
src/view/counter.js:

import { useDispatch } from 'react-redux';
import {
  decrement,
  // increment,
  incrementByAmount,
  // incrementAsync,
  // incrementIfOdd,
  // selectCount,
} from './../logic/slice';
export function Counter() {
  const dispatch = useDispatch();
  return (
    <div>
        <button
          className={styles.button}
          aria-label="Decrement value"
          onClick={() => dispatch(decrement())}
        >-
        </button>
        <button
          className={styles.button}
          aria-label="Increment value"
          onClick={() => dispatch(incrementByAmount(2)}
        >
          +
        </button>
    </div>
  )
}

苏南大叔:create-react-app的redux范例,如何通过dispatch修改state? - 调用actions
create-react-app的redux范例,如何通过dispatch修改state?(图5-3)

核心代码:

import { useDispatch } from 'react-redux';
const dispatch = useDispatch();
// dispatch(decrement())
// dispatch(incrementByAmount(2))

特例reducer的写法

slice.js中定义了一个游离在createSlice()外部的reducer,叫做incrementIfOdd()

export const selectCount = (state) => state.store_reducer_name.value;
export const getState = (state) => {
  return state.store_reducer_name;
}
export const incrementIfOdd = (amount) => (dispatch, getState) => {
  const currentValue = selectCount(getState());
  if (currentValue % 2 === 1) {
    dispatch(incrementByAmount(amount));
  }
};

苏南大叔:create-react-app的redux范例,如何通过dispatch修改state? - 特殊函数用法
create-react-app的redux范例,如何通过dispatch修改state?(图5-4)

特殊点一:函数incrementIfOdd()

  • 拥有两个=>,苏南大叔目前认为:可能是后面的()=>{}返回了一个{},然后和第一个()=>做了个组合。
  • 局部变量dispatchgetState,代表两个函数。其中dispatch的用法和上一节中说的一样。getState和想象中的一样。因为是局部变量,和全局自定义的getState()没有关系。

特殊点二:函数selectCount()

这是个获得state的函数,在这个例子里面,结论是:要看使用函数的调用位置,来决定使用的方式。

  • 使用方式并不是const currentValue = useSelector(selectCount)
  • 而是常规的const currentValue = selectCount(getState())

特殊点三:函数incrementIfOdd()调用方式

这个定义在slice之外的action,调用方式和定义在slice之内的action是一样的。

onClick={() => dispatch(incrementByAmount(2))}
onClick={() => dispatch(incrementIfOdd(2))}

特殊点四:函数incrementIfOdd()type

  • incrementIfOdd()没有定义在reducers里面,没有type,不会留痕,无法回访。
  • 内部有条件地调用了dispatch(incrementByAmount(amount)),只有调用的时候,才会留痕支持回访。而且回放的也是incrementByAmount,无法体现incrementIfOdd的存在。

特殊点五:对于incrementIfOdd()来说,有两个dispatch

  • 外部调用一个,onClick={() => dispatch(incrementIfOdd(incrementValue))}
  • 内部调用一个,而且还是个局部变量(dispatch, getState) => {}

关于action.type

其实每个被dispatch的函数,都有个type。这些没有被显示定义type的,都会被自动生成一个名字。规则就是:
slice的名字+函数的名字。下面的是redux-devtools的相关截图:

苏南大叔:create-react-app的redux范例,如何通过dispatch修改state? - action
create-react-app的redux范例,如何通过dispatch修改state?(图5-5)

至于这个叫做reducer还是叫做action,确实有些混乱。苏南大叔是这么理解的:

  • 定义的时候,这个就叫做reducer
  • slice加工过的reducer,或者说被dispatch调用的,就叫做action

相关文档

综述

更多redux的经验文章,请点击:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   react    redux