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

时间:2019-02-25 12:01:03

标签: reactjs react-hooks

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

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

https://codepen.io/vitalyster/pen/LaPMJO

7 个答案:

答案 0 :(得分:17)

传递给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>);
}

Working demo

答案 1 :(得分:2)

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

例如您的情况,这将完成您的工作

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

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

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

React.useEffect(FunctionYouWantToRunAfterEveryRender)

如果仅将一个参数传递给useEffect,则它将在每次渲染后运行此方法 您可以通过将第二个参数传递给useEffect

来决定何时触发此FunctionYouWantToRunAfterEveryRender
React.useEffect(FunctionYouWantToRunAfterEveryRender, [props.user])

您注意到我现在正在传递[props.user],useEffect仅在更改FunctionYouWantToRunAfterEveryRender时才会触发此props.user函数

我希望这可以帮助您理解 让我知道是否需要任何改进

答案 2 :(得分:1)

我已经创建了这样的自定义钩子:

app.append(`<span>${anyValue}</span>`);

使用:

const usePrevious = value => {
   const ref = React.useRef();

   React.useEffect(() => {
       ref.current = value;
   }, [value]);

   return ref.current;
}

const usePropState = datas => {
    const [dataset, setDataset] = useState(datas);
    const prevDatas = usePrevious(datas);

    const handleChangeDataset = data => setDataset(data);

    React.useEffect(() => {
        if (!deepEqual(datas, prevDatas)) // deepEqual is my function to compare object/array using deep-equal
            setDataset(datas);
    }, [datas, prevDatas]);

    return [
        dataset,
        handleChangeDataset
    ]
}

答案 3 :(得分:1)

您可以为此创建自己的自定义简单钩子。钩子在更改时更改了默认值。

https://gist.github.com/mahmut-gundogdu/193ad830be31807ee4e232a05aeec1d8

import {useEffect, useState} from 'react';

export function useStateWithDep(defaultValue: any) {
  const [value, setValue] = useState(defaultValue);

  useEffect(() => {
    setValue(defaultValue);
  }, [defaultValue]);
  return [value, setValue];
}

// 示例

// const [user, setUser] = useStateWithDep(props.user);

答案 4 :(得分:0)

根据ReactJS documentation about Hooks

  

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

您唯一的互动应该在道具更改时进行,这似乎不起作用。您可以(仍然根据文档)使用componentDidUpdate(prevProps)来主动捕获对道具的任何更新。

PS:我没有足够的代码来判断,但是您不能在Avatar(props)函数内部积极设置setUser()吗?

答案 5 :(得分:0)

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

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

答案 6 :(得分:-1)

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