链接 useEffects 使用先前效果的更新状态时出现问题

问题描述 投票:0回答:3

我有一个需要一些复杂数据获取的应用程序。总的来说,这是我的应用程序中逻辑的快照

// dep1 is from redux, dep2 is local state

// useEffect 1
useEffect(() => {
   // perform some state variable update to dep2
}, [dep1]);

// useEffect 2
useEffect(() => {
   // use some values from deps to fetch data
}, [dep1, dep2]);

我面临的问题是,当 dep1 和/或 dep2 更新时,useEffect 1 的状态更改需要反映在 useEffect 2 中数据获取操作的请求 url 中。useEffect 2 最终运行两次,一次是在 dep1 更新时运行的(没有来自 url 中 useEffect 1 的 dep2 更新)以及一次使用 dep2 更新。在大多数情况下,我们只是渲染,这个问题并不特别明显,但在 useEffect 中使用数据获取的情况下,我们最终会得到两次 api 获取。我可以使用什么策略来规避这种双重 API 调用?

编辑 添加更多代码以使问题更加具体:

// useEffect 1
// when the user is changed (user is a prop that is from redux),
// option should be reset to "DEFAULT"
useEffect(() => {
    setOption("DEFAULT");
}, [currentUser]);

// useEffect 2
// option is a value that can be set within the UI and is local state.
// setting option to a new value will trigger api call with new value
useEffect(() => {
    const data = await getData(option);
}, [currentUser, option]);

当选项不是“DEFAULT”且当前用户更改时,useEffect 2 将运行两次的问题。我想找到一些逻辑,允许它在当前用户更改时运行一次,并将选项设置回“默认”。使用其他反应模式是否可以实现这一点,因为 useEffect 似乎不可能?

javascript reactjs react-hooks closures use-effect
3个回答
0
投票

我认为你让事情变得更加复杂了。我建议使用单个效果钩子并计算逻辑并以相同的效果执行数据获取。

/ dep1 is from redux, dep2 is local state

// useEffect 1
useEffect(() => {
   // perform some state variable update to dep2
   // perform data fetching here and if you want to check some condition for dep2 you could do that here as well.

}, [dep1]);

0
投票

尝试在当前组件内的 React 组件中设置 dep2 并将其作为 prop 传递,这样每个组件中只有一个 useEffect,并且状态被向上传递。

const component = () => {

    useEffect(() => {
       // do something
    }, [dep1]);
    
    
    return (
           <div> <ComponentTwo depTwo={depTwo}/> </div>
    )
}

然后在 ComponentTwo 中...

const componentTwo = ({ depTwo }) => {

    // useEffect 2
    useEffect(() => {
       // use some values from deps to fetch data
    }, [dep2]);
    
    
    return (<div> something </div>
    
    )
}

您需要在父组件中导入 ComponentTwo。


0
投票

我想找到一些逻辑,允许它在当前用户更改时运行一次,并将选项设置回“默认”。

逻辑

让我们尽量避免在这两种情况下更新状态。如果我正确理解了这种情况,那么从逻辑上讲,我们正在研究 2 个被视为标志的变量的 4 种排列(布尔值/真值): 变量

选项 -
    [0
  • :默认 / 1(用户更新)] 用户 -
  • [0
  • :现有 / 1(redux 已更新)]
  • 可变状态案例

情况 1.
    [00]
  • 初始状态 - 默认选项,现有用户 案例 2.
  • [01]
  • 用户已更新 - 默认用户,用户 案例 3.
  • [10]
  • 选项已更新 - 选项,现有用户 案例 4.
  • [11]
  • 用户和选项已更新 - 用户,选项
  • 注意事项

我假设在 redux 设置 user 属性之前你不会尝试渲染。但如果是这种情况,我可以更新答案,给出更多关于如果用户为 null 时预计如何处理选项/api 调用的上下文。

对于 (4)(新用户,新选项)的情况,我们通过用户 AI 输入处理组件本身内的选项状态更新,因此无法通过单次重新渲染达到此状态。由于 redux,它正在有效地过渡到 [2],然后由于(且仅在)用户输入之后过渡到 [3]。

让我们确保处理所有情况,这样在每种情况下,我们只调用 API 一次。

代码

假设您的默认选项状态为空

const [option, setOption] = useState(null)

案例1、案例2

此效果将在初始渲染时运行一次,并在 currentUser 更改时运行一次。

证明(反应文档)

. // useEffect 1 // when the user is changed ([currentUser] is a prop that is from redux) // [we want to render with default options] useEffect(() => { const data = await getData("DEFAULT"); }, [currentUser]);

案例3、案例4

此效果将在初始渲染时运行一次,并且在依赖项(选项)更改时运行一次。

// useEffect 2 // option is a value that can be set within the UI and is local state. // If the user updates the option to a new value [we want to render with user options] useEffect(() => { // to avoid two calls on the initial render, add an if statement if (option){ const data = await getData(option); } // else, this is the initial render; }, [option]);

进一步阅读/解释

因为您声明默认选项更改是用户更改的结果,所以默认选项 api 调用是在 userEffect1 中进行的。后续 api 调用是用户通过 UI 更新选项的结果,因此从逻辑上讲,后续 api 调用是通过选项依赖项 userEffect2 来实现的。

由于最后一种情况 (4) 只是处理 (2) 和 (3) 的情况,在它们单独但顺序的状态下,我们已经涵盖了这两个变量的所有排列。

我们可以依靠 useEffect1 来检索默认数据,而不是将选项状态设置为“DEFAULT”,假设我们不使用/要求选项状态执行更多操作而不是获取非默认数据。

注意

,使用 null 而不是“DEFAULT”作为选项状态的默认值使我们能够区分初始用户或新用户以及选择默认选项的现有用户,以防用户可以选择“DEFAULT” “作为一个选项。

© www.soinside.com 2019 - 2024. All rights reserved.