Aqui está o problema: estou tentando chamar duas funções com um clique de botão. Ambas as funções atualizam o estado (estou usando o gancho useState). A primeira função atualiza o valor1 corretamente para 'novo 1', mas após 1s (setTimeout) a segunda função é acionada e altera o valor 2 para 'novo 2' MAS! Ele define o valor1 de volta para '1'. Por que isso está acontecendo? Desde já, obrigado!
import React, { useState } from "react";
const Test = () => {
const [state, setState] = useState({
value1: "1",
value2: "2"
});
const changeValue1 = () => {
setState({ ...state, value1: "new 1" });
};
const changeValue2 = () => {
setState({ ...state, value2: "new 2" });
};
return (
<>
<button
onClick={() => {
changeValue1();
setTimeout(changeValue2, 1000);
}}
>
CHANGE BOTH
</button>
<h1>{state.value1}</h1>
<h1>{state.value2}</h1>
</>
);
};
export default Test;
javascript
reactjs
react-hooks
Bartek
fonte
fonte
changeValue2
?useState
ou useuseReducer
.const [state, ...]
e, em seguida, referindo-se a ele no levantador ... Ele usará o mesmo estado o tempo todo.useState
chamadas separadas , uma para cada "variável".Respostas:
Bem-vindo ao inferno do fechamento . Esse problema ocorre porque sempre que
setState
é chamado,state
obtém uma nova referência de memória, mas as funçõeschangeValue1
echangeValue2
, por causa do fechamento, mantêm astate
referência inicial antiga .Uma solução para garantir o estado
setState
dechangeValue1
echangeValue2
obtém o estado mais recente é usando um retorno de chamada (tendo o estado anterior como parâmetro):Você pode encontrar uma discussão mais ampla sobre esse problema de fechamento aqui e aqui .
fonte
Suas funções devem ser assim:
Portanto, verifique se não está faltando nenhuma propriedade existente no estado atual usando o estado anterior quando a ação é acionada. Além disso, você evita ter que gerenciar fechamentos.
fonte
Quando
changeValue2
é invocado, o estado inicial é mantido para que o estado volte ao estado inicial e, em seguida, avalue2
propriedade é gravada.A próxima vez que
changeValue2
for invocada depois disso, ele mantém o estado{value1: "1", value2: "new 2"}
, portanto, avalue1
propriedade é substituída.Você precisa de uma função de seta para o
setState
parâmetro.fonte
O que está acontecendo é que ambos
changeValue1
echangeValue2
ver o estado do renderizar eles foram criados em , por isso, quando o componente de tornar pela primeira vez estes 2 funções, consulte:Quando você clica no botão,
changeValue1
é chamado primeiro e altera o estado para{value1: "new1", value2: "2"}
o esperado.Agora, após 1 segundo,
changeValue2
é chamado, mas essa função ainda vê o estado inicial ({value1; "1", value2: "2"}
), portanto, quando essa função atualiza o estado da seguinte maneira:setState({ ...state, value2: "new 2" });
você acaba vendo:
{value1; "1", value2: "new2"}
.fonte
fonte