【问题标题】:How to handle, after state change in React context dispatchReact 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'
    }
})

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

【问题讨论】:

    标签: javascript reactjs react-context use-reducer use-context


    【解决方案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 钩子中没有“历史”或“更改日志”功能。因此,跟踪更改的唯一方法是将它们存储在某个地方。
    猜你喜欢
    • 2019-02-21
    • 2022-10-13
    • 2020-03-29
    • 2021-06-25
    • 1970-01-01
    • 1970-01-01
    • 2020-07-04
    • 2019-05-02
    • 1970-01-01
    相关资源
    最近更新 更多