51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

React的`useEffect`钩子依赖于另一个`useEffect`。

英文:

React useEffect hook that depends on another useEffect

问题 {#heading}

I'll provide the translated code portion as requested:

我的NextJS 13项目中有一个组件,其中包含两个useEffect钩子,一个用于设置名为singleRecipe的React上下文状态数组变量,另一个我想要设置另一个名为ingredientsArr的局部状态变量。问题出现在首次渲染时,当我的代码到达第二个useEffect时,我收到了未定义的singleRecipe状态变量。一旦singleRecipe被定义,我该如何将ingredientsArr变量更新为singleRecipe中的一个元素?

useEffect(() => { setSingleRecipe(recipes.find(({id}) => id === Number(recipeID))) })

useEffect(() => { setIngredientsArr(JSON.parse(singleRecipe.ingredients)) }, [singleRecipe])

  • singleRecipe存储在上下文状态中,ingredientsArr是这个组件的局部变量

英文:

A component in my NextJS 13 project has two useEffect hooks, one that sets a React Context state array variable called singleRecipe, and another that I would like to set another local state variable called ingredientsArr. The issue arises on first render, I am receiving undefined for the singleRecipe state variable when my code reaches the second useEffect. How would I go about updating the ingredientsArr variable to an element from the singleRecipe only once singleRecipe is defined?

useEffect(() => {
  setSingleRecipe(recipes.find(({id}) => id === Number(recipeID)))
})
`useEffect(() => {
setIngredientsArr(JSON.parse(singleRecipe.ingredients))
}, [singleRecipe])
`

  • singleRecipe is stored in context state and ingredientsArr is local to this component

答案1 {#1}

得分: 2

Sure, here are the translations of the code-related content:

> I am receiving undefined for the singleRecipe state variable

我得到了未定义的单一食谱状态变量。

You can check if the value is undefined before trying to use it. For example:

在尝试使用它之前,您可以检查该值是否为 undefined。例如:

useEffect(() => {
  if (singleRecipe) {
    setIngredientsArr(JSON.parse(singleRecipe.ingredients))
  }
}, [singleRecipe])

或者可以使用可选链,并在整体值为"falsy"时有条件地设置为空数组:

或者,如果目标是在一个 整体效果中执行这两个操作,只需使用一个useEffect调用:

useEffect(() => {
  setIngredientsArr(JSON.parse(singleRecipe?.ingredients ?? '[]'))
}, [singleRecipe])

或者,如果目标是在一个 整体效果中执行这两个操作,只需使用一个useEffect调用:

useEffect(() => {
  const newRecipe = recipes.find(({ id }) => id === Number(recipeID));
  setSingleRecipe(newRecipe);
  setIngredientsArr(JSON.parse(newRecipe.ingredients));
});

It's worth noting, if only for future readers... This effect will run on every render . Which is probably not what you want. Especially if the effect updates state, which triggers another render.

值得注意的是,仅供将来的读者参考... 这个效果将在每次渲染 时运行。这可能 不是您想要的。特别是如果效果更新状态,这会触发另一个渲染。

You can modify this effect to only run on the first render by providing an empty dependency array:

您可以通过提供一个空的依赖数组来修改此效果,以便仅在第一次渲染时运行:

useEffect(() => {
  const newRecipe = recipes.find(({ id }) => id === Number(recipeID));
  setSingleRecipe(newRecipe);
  setIngredientsArr(JSON.parse(newRecipe.ingredients));
}, []); // <--- here

或者只在recipeID更改时运行:

或者只在recipeID更改时运行:

useEffect(() => {
  const newRecipe = recipes.find(({ id }) => id === Number(recipeID));
  setSingleRecipe(newRecipe);
  setIngredientsArr(JSON.parse(newRecipe.ingredients));
}, [recipeID]); // <--- here

英文:

> I am receiving undefined for the singleRecipe state variable

You can check if the value is undefined before trying to use it. For example:

useEffect(() => {
  if (singleRecipe) {
    setIngredientsArr(JSON.parse(singleRecipe.ingredients))
  }
}, [singleRecipe])

Or perhaps use optional chaining and conditionally set to a blank array if the overall value is "falsy":

useEffect(() => {
  setIngredientsArr(JSON.parse(singleRecipe?.ingredients ?? '[]'))
}, [singleRecipe])

Alternatively, if the goal is to perform both of these operations in one overall effect then just use one call to useEffect:

useEffect(() => {
  const newRecipe = recipes.find(({id}) => id === Number(recipeID));
  setSingleRecipe(newRecipe);
  setIngredientsArr(JSON.parse(newRecipe.ingredients));
});

It's worth noting, if only for future readers... This effect will run on every render . Which is probably not what you want. Especially if the effect updates state, which triggers another render.

You can modify this effect to only run on the first render by providing an empty dependency array:

useEffect(() => {
  const newRecipe = recipes.find(({id}) => id === Number(recipeID));
  setSingleRecipe(newRecipe);
  setIngredientsArr(JSON.parse(newRecipe.ingredients));
}, []); // <--- here

Or to run only when recipeID changes:

useEffect(() => {
  const newRecipe = recipes.find(({id}) => id === Number(recipeID));
  setSingleRecipe(newRecipe);
  setIngredientsArr(JSON.parse(newRecipe.ingredients));
}, [recipeID]); // <--- here

答案2 {#2}

得分: 1

你这里实际上不需要两个 useEffect:

useEffect(() => {
  const myRecipe = recipes.find(({id}) => id === Number(recipeID));
  setSingleRecipe(myRecipe);
  setIngredientsArr(JSON.parse(myRecipe.ingredients));
}, []); // 空的依赖数组,只在第一次渲染后运行一次

注意,在你的代码中,第一个 useEffect 没有依赖数组,因此会在每次组件渲染时运行。

英文:

you don't really need two useEffect here:

useEffect(() => {
  const myRecipe = recipes.find(({id}) => id === Number(recipeID));
  setSingleRecipe(myRecipe);
  setIngredientsArr(JSON.parse(myRecipe.ingredients));
}, []); // empty dependency array to run onlu once after the first render

Note that in your code the first useEffect will run on each component render because it does not have a dependency array.

答案3 {#3}

得分: 0

可以通过在第二个 useEffect 中添加一个检查来实现这一点:

useEffect(() => {
  setSingleRecipe(recipes.find(({ id }) => id === Number(recipeID)))
})

useEffect(() => { if (!singleRecipe) return; setIngredientsArr(JSON.parse(singleRecipe.ingredients)) }, [singleRecipe])

虽然第一个 useEffect 没有依赖项似乎很奇怪。recipeId 是什么?如果它是一个 prop 或者 state 变量,你可能应该将它包含在依赖数组中:

useEffect(() => {
  setSingleRecipe(recipes.find(({ id }) => id === Number(recipeID)))
}, [recipeId])

如果不将其包含在依赖数组中,它将在每次渲染时设置,这并不理想。

它为什么未定义是因为你在第一个 useEffect 中设置它,状态更新是异步的(因此新值在下一次渲染之前不可用)。 英文:

I think you can achieve this by adding a check to the second use effect:

useEffect(() => {
  setSingleRecipe(recipes.find(({id}) => id === Number(recipeID)))
})
`useEffect(() => {
if(!singleRecipe) return;
setIngredientsArr(JSON.parse(singleRecipe.ingredients))
}, [singleRecipe])
`

Although it seems strange that the first useEffect has no dependencies. What is recipeId? If that is a prop/state var you should probably include it in the dep array:

useEffect(() => {
  setSingleRecipe(recipes.find(({id}) => id === Number(recipeID)))
}, [recipeId])

If you don't include it in the dep array, it will set it on every render which isn't ideal.

The reason it's undefined is you are setting it in the first useEffect and state updates asynchronously (so the new value isn't available until the next render).


赞(3)
未经允许不得转载:工具盒子 » React的`useEffect`钩子依赖于另一个`useEffect`。