React.useState não recarrega o estado dos adereços

109

Estou esperando o estado recarregar na mudança de props, mas isso não funciona e a uservariável não é atualizada na próxima useStatechamada, o que está errado?

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

codepen

vitalyster
fonte

Respostas:

244

O argumento passado para useState é o estado inicial, assim como definir o estado no construtor para um componente de classe e não é usado para atualizar o estado na re-renderização

Se você quiser atualizar o estado na mudança de suporte, use o useEffectgancho

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>);
}

Demonstração de trabalho

Shubham Khatri
fonte
21
Ao definir o estado inicial no construtor, é claro entender que o construtor é chamado uma vez na criação da instância da classe. Com ganchos, parece que useState é chamado a cada vez na chamada de função e a cada vez que deve inicializar o estado, mas alguma "mágica" inexplicável acontece lá.
vitalyster de
Talvez este post lance alguma luz sobre isso stackoverflow.com/questions/54673188/…
Shubham Khatri
1
se você precisar mesclar adereços no estado, ficará preso em um loop infinito ao usar o aplicativo create-react-app, que requer que o estado esteja na matriz de dependência
user210757
2
Isso acaba configurando o estado inicial duas vezes, o que é muito chato. Eu me pergunto se você pode definir o estado inicial como nulo e usar React.useEffectpara definir o estado inicial a cada vez.
CMCDragonkai
3
Isso não funciona se o estado também estiver controlando a renderização. Eu tenho um componente funcional que renderiza com base em adereços e renderiza com base no estado. Se o estado instruir o componente a renderizar porque foi alterado, useEffect será executado e definirá o estado de volta para o valor padrão. Este é um projeto realmente ruim da parte deles.
Greg Veres
2

Componentes funcionais onde usamos useStatepara definir valores iniciais para nossa variável, se passarmos o valor inicial através de props, ele sempre definirá o mesmo valor inicial até que você não faça uso do useEffectgancho,

por exemplo, seu caso, isso fará seu trabalho

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

A função passada para useEffect será executada depois que a renderização for confirmada na tela.

Por padrão, os efeitos são executados após cada renderização concluída, mas você pode optar por dispará-los apenas quando certos valores forem alterados.

React.useEffect(FunctionYouWantToRunAfterEveryRender)

se você passar apenas um argumento para useEffect, ele executará este método após cada renderização, você pode decidir quando dispará-lo FunctionYouWantToRunAfterEveryRenderpassando o segundo argumento para useEffect

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

como você notou que estou passando [props.user] agora useEffectsó disparará esta FunctionYouWantToRunAfterEveryRenderfunção quando props.userfor alterada

Espero que isso ajude sua compreensão, deixe-me saber se alguma melhoria é necessária, obrigado

Hanzla Habib
fonte
1

O parâmetro passado React.useState()é apenas o valor inicial desse estado. O React não vai reconhecer isso como uma mudança de estado, apenas definindo seu valor padrão. Você deve definir o estado padrão inicialmente e, em seguida, chamar condicionalmentesetUser(newValue) , que será reconhecido como um novo estado, e renderizar novamente o componente.

Eu recomendaria cautela ao atualizar o estado sem algum tipo de condição para evitar que ele atualize constantemente e, portanto, renderizar novamente toda vez que os acessórios forem recebidos. Você pode querer considerar içar a funcionalidade de estado para um componente pai e passar o estado do pai para este Avatar como um suporte.

Sonolento
fonte
-2

De acordo com a documentação do ReactJS sobre Ganchos :

Mas o que acontece se o acessório amigo mudar enquanto o componente estiver na tela? Nosso componente continuaria exibindo o status online de um amigo diferente. Este é um bug. Também causaríamos um vazamento de memória ou travamento ao desmontar, já que a chamada de cancelamento de inscrição usaria o ID de amigo errado.

Sua única interação aqui deve acontecer em uma mudança de adereços, o que parece não funcionar. Você poderia (ainda de acordo com o documento) usar um componentDidUpdate (prevProps) para capturar de forma proativa qualquer atualização para os adereços.

PS: Eu não tenho código suficiente para julgar, mas você não poderia ativamente setUser () dentro da função Avatar (adereços)?

Mwak
fonte
-12

No mundo reactivo, você deve atualizar seu estado na função componentWillRecieveProps (nextProps), nesses casos.

Sushil Mahajan
fonte
4
O que não é mais verdade para as versões mais recentes do
react