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

huangapple go评论119阅读模式
英文:

React useEffect hook that depends on another useEffect

问题

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

得分: 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

得分: 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

得分: 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).

huangapple
  • 本文由 发表于 2023年8月11日 02:07:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76878299.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定