React.useState不会从props重新加载状态


109

我期望状态在道具更改时重新加载,但这不起作用,并且user变量在下次useState调用时不会更新,这是怎么回事?

function Avatar(props) {
  const [user, setUser] = React.useState({...props.user});
  return user.avatar ? 
         (<img src={user.avatar}/>)
        : (<p>Loading...</p>);
}

码笔

Answers:


243

传递给useState的参数是初始状态,就像在类组件的构造函数中设置状态一样,并且不用于在重新渲染时更新状态

如果您想在道具变更时更新状态,请使用useEffect钩子

function Avatar(props) {
  const [user, setUser] = React.useState({...props.user});

  React.useEffect(() => {
      setUser(props.user);
  }, [props.user])

  return user.avatar ? 
         (<img src={user.avatar}/>)
        : (<p>Loading...</p>);
}

工作演示


21
在构造函数中设置初始状态时,可以很清楚地了解到在构造类实例时会一次调用构造函数。对于钩子,每次函数调用时和每次它应该初始化状态时,都会调用useState,但是在那里发生了一些无法解释的“魔术”。
vitalyster '19

也许这个帖子一些线索它stackoverflow.com/questions/54673188/...
Shubham卡特里

1
如果您需要将道具合并到状态中,则在使用create-react-app时会陷入无限循环,该状态要求状态位于依赖项数组中
user210757 '19

2
最终设置了两次初始状态,这很烦人。我想知道是否可以将初始状态设置为null,然后React.useEffect每次使用来设置初始状态。
CMCDragonkai

3
如果状态也在控制渲染,则此方法不起作用。我有一个功能组件,该组件基于props和状态进行渲染。如果状态因为更改而通知组件进行渲染,则useEffect会运行并将状态设置回默认值。对他们而言,这确实是糟糕的设计。
格雷格·韦雷斯

2

我们用来useState为变量设置初始值的功能组件,如果我们通过prop传递初始值,它将始终设置相同的初始值,直到您不使用useEffect钩子,

例如你的情况,这将做你的工作

 React.useEffect(() => {
      setUser(props.user);
  }, [props.user])

传递给useEffect的函数将在将渲染提交到屏幕后运行。

默认情况下,效果会在每个完成的渲染之后运行,但是您可以选择仅在某些值更改后才触发效果。

React.useEffect(FunctionYouWantToRunAfterEveryRender)

如果仅将一个参数传递给useEffect,则它将在每次渲染后运行此方法,您可以FunctionYouWantToRunAfterEveryRender通过将第二个参数传递给useEffect来决定何时触发该方法

React.useEffect(FunctionYouWantToRunAfterEveryRender, [props.user])

如您所知,我正在传递[props.user]现在useEffectFunctionYouWantToRunAfterEveryRenderprops.user更改时会触发此功能

我希望这有助于您的理解,让我知道是否需要任何改进,谢谢


1

传递给的参数React.useState()只是该状态的初始值。React不会将其识别为更改状态,而只是设置其默认值。您将需要先设置默认状态,然后有条件地调用setUser(newValue),它将被识别为新状态,然后重新渲染该组件。

我建议谨慎更新状态,而无需某种条件以防止其不断更新,因此,每次接收到道具时都要重新渲染。您可能需要考虑将状态功能提升到父组件,并将父状态作为道具传递给此头像。


-2

根据关于HooksReactJS文档

但是,如果组件在屏幕上时好友道具发生变化,会发生什么?我们的组件将继续显示其他朋友的在线状态。这是一个错误。由于取消订阅调用将使用错误的朋友ID,因此在卸载时,我们还会导致内存泄漏或崩溃。

您在此处的唯一互动应该是在道具更改上发生的,这似乎不起作用。您可以(仍根据文档)使用componentDidUpdate(prevProps)主动捕获对道具的任何更新。

PS:我没有足够的代码来判断,但是您不能在Avatar(props)函数中主动setUser()吗?


-12

在react world中,在这种情况下,您应该在componentWillRecieveProps(nextProps)函数中更新状态。


4
对于最新版本的react不再适用
Shubham Khatri
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.