React context dispatch 状态改变后如何处理

Posted

技术标签:

【中文标题】React context dispatch 状态改变后如何处理【英文标题】:How to handle, after state change in React context dispatch 【发布时间】:2020-10-15 13:49:41 【问题描述】:

我有一个 React 版本 16 应用程序。使用 React 的 Context、reducer 概念处理状态更改。

要更改状态并执行更改后的操作,可以按以下方式处理。例如 - 我在组件“联系人”中。在这里面,我在一个变量 age 上发送一个状态变化,它是一个如下给出的数字 -

dispatch(
    type: "CHANGE_AGE",
    payload: age
)

并在减速器中捕获调度,如下所示

case "CHANGE_AGE":
    return 
        ...state,
        age: action.payload
    

要在'Contact'组件中做一些年龄变化后,我们可以使用'useEffect'来观察'age'的变化

useEffect(
    //doSomething()
,[state.age])

问题是 - 如果我们不得不改变一个处于状态的对象,也就是说,我们必须改变地址,而不是改变年龄,就像下面给出的那样,我们必须在地址改变后做一些事情。

我们如何观察地址变化?

dispatch(
    type: "CHANGE_ADDRESS",
    payload: 
        city: "Delhi",
        country: "India",
        zip: '22233'
    
)

一个可能的解决方案 - 除了地址分派之外,我们还可以分派一个变量,我们可以根据它的变化来做一些事情。但这不是一个完美的解决方案。

【问题讨论】:

【参考方案1】:

只存储前一个地址和当前地址

// your-state.js
const initialState = 
  age: 0,
  prevAdress: 
    city: '',
    country: '',
    zip: ''
  ,
  currAdress: 
    city: '',
    country: '',
    zip: ''
  ,
  ...

当你派发时,把当前写在reducer中

// your-reducer.js
...
case "CHANGE_ADDRESS":
    return 
        ...state,
        prevAddress:  ...state.currAddress ,
        currAddress:  ...action.payload 
    

然后在效果中比较

// your-component.js
...
useEffect(() => 
  if (state.prevAddress.zip !== state.currAddress.zip)  // just an example of comparison
    // doSmthg
  
, [state]);
...

更新

如果您只需要比较地址一次并根据该比较执行某些操作,那么只需在分派值之前进行比较:

// your-component.js
...
useEffect(() => 
  const doDispatch = () => dispatch(
        type: "CHANGE_ADDRESS",
        payload: 
          city: "Delhi",
          country: "India",
          zip: newZip,
        ,
      );

  if (state.address.zip !== newZip) 
    doSmthgAsPromise().then(() =>      // do something and then dispatch
      doDispatch();
    );
   else 
    doDispatch();
  
, [state, dispatch, doSmthgAsPromise]);

【讨论】:

这是一个不错的方法。我的问题 - 如果我们有许多保存对象值的状态变量怎么办,我们应该为每个变量设置 prev 和 current 变量吗?您还能想到其他方法吗? 这取决于你的目的。如果您想在不同的时间点多次比较它们,我认为您必须为每个都有 prev/curr。如果您只想检查一次,只需在我的 update 中查看解决方案 我看到了你的更新。我看到的唯一缺点是它最终会出现在许多本地状态变量中,比如我们必须比较的 newZip。假设我的目的是更新,并且我可以更新该地址对象中的任何内容,就像地址对象一样,如果我有许多其他状态变量(对象类型)......? 我不确定您的最终目标是什么。 React Context 或 useReducer 钩子中没有“历史”或“更改日志”功能。因此,跟踪更改的唯一方法是将它们存储在某个地方。

以上是关于React context dispatch 状态改变后如何处理的主要内容,如果未能解决你的问题,请参考以下文章

React Context 详细介绍(状态共享数据传递)

ReactJS Redux State(全局状态)+ React.Context(本地状态)

useReducer 和 useState

Redux状态更改后,简单的React组件不会更新

在 dataProvider react-admin 中使用 dispatch

如何为 useReducer 键入 state 和 dispatch - typescript 和 react