React + useState () + previousState
Eu sou muito novo para reagir e tenho problemas em entender o uso do Gancho do Estado - ou mais especificamente o aspecto do Estado anterior .
Um useState Hook normal, e provavelmente o exemplo mais comum, tem a seguinte aparência:
import React, { useState} from 'react';
export default function CounterHooks({ initialCount }){
const [count, setCount] = useState(initialCount);
return (
<div>
<button onClick={() => setCount(count -1)}>-</button>
<span>{count}</span>
<button onClick={() => setCount(count + 1)}>+</button>
</div>
)
}
O que estou entendendo até agora é o seguinte:
- Eu chamo a função useState () / Gancho? e passar o argumento do estado inicial (initialCount)
- Eu recebo de volta um array que imediatamente destruo nas variáveis count e setCount (que é função)
- Com setCount () posso atualizar o estado e, portanto, a variável de contagem
Até aí tudo bem, eu acho ...;)
Às vezes vejo o mesmo contra-exemplo com prevState (prevCount), que não entendo:
<button onClick={() => setCount(prevCount => prevCount -1)}>-</button>
o que acontece aqui? Esta parte eu não entendo. Meus pensamentos até agora:
- Nesse caso, de alguma forma eu acesso o valor de contagem anterior.
- setCount espera agora uma função
- setCount agora é executado de forma assíncrona
- De onde vem essa função?
- De onde vem o prevCount?
- Quando eu executo isso, o que é colocado em prevCount?
Você entende minha confusão? Não tenho certeza de como devo enquadrar isso de forma diferente ...
Muito obrigado por sua ajuda.
Respostas
Em primeiro lugar, você pode ver a explicação oficial aqui .
Nesse caso, de alguma forma eu acesso o valor de contagem anterior.
Você não está de alguma forma acessando o valor de contagem anterior. Se você usar uma atualização funcional e fornecer uma função de retorno de chamada ao configurador, ele retornará o estado anterior para você e você usará esse valor em sua função de retorno de chamada.
setCount espera agora uma função
Como você fornece uma função, ele pode usá-la.
setCount agora é executado de forma assíncrona
Na verdade não. Não é uma função assíncrona. Ele apenas fornece o estado anterior e você o usa. Os configuradores de estado não são assíncronos, a atualização de estado é.
De onde vem essa função?
De onde vem o prevCount?
Já respondido.
Quando eu executo isso, o que é colocado em prevCount?
Você fornece o que deseja que defina o novo estado lá. Em seu exemplo, você deseja incrementar countem 1, então está fornecendo+ 1
Aqui está uma explicação ingênua para essa lógica. Apenas um ingênuo. Estou adicionando isso para exemplificar a lógica de retorno de chamada, isso não está relacionado ao ReactsetState.
let state = 5;
function setState(val) {
if (typeof val === "function") {
return val(state);
}
return val;
}
const stateWithFunctionalUpdate = setState(prev => prev + 1);
const stateWithNormalUpdate = setState(9);
console.log(stateWithFunctionalUpdate);
console.log(stateWithNormalUpdate);
Talvez este exemplo seja adequado para simular a lógica de configuração de estado do React. Novamente, apenas uma abordagem ingênua.
let state = 5;
function setState(val) {
if (typeof val === "function") {
state = val(state);
} else {
state = val;
}
}
setState(9);
setState(prev => prev + 1);
console.log("state", state);
Vejamos a implementação real de useState(sem tipificações):
export function useState(initialState) {
return useReducer(
basicStateReducer,
// useReducer has a special case to support lazy useState initializers
initialState
);
}
Bem, ele só usa useReduceratrás das cortinas. Ele define o estado inicial e usa basicStateReducer que é:
function basicStateReducer(state, action) {
return typeof action === "function" ? action(state) : action;
}
Como nossa abordagem ingênua, ele procura o tipo de actione se comporta de acordo com isso. Finalmente, isso é o que useReducer retorna :
return [workInProgressHook.memoizedState, dispatch];
Portanto, no final do dia, se fornecermos uma função para useState, ele a pega e, em seguida, a executa em nosso estado e retorna o valor de volta.
Aqui está minha opinião como eu entendo:
Nesse caso, de alguma forma eu acesso o valor de contagem anterior. -> setCount verificará o parâmetro, se o parâmetro for um retorno de chamada, ele fará a chamada de retorno e passará o estado anterior para o parâmetro. O resultado da chamada de volta será o próximo estado.
setCount espera agora uma função -> sim, a função manipula sua lógica e retorna o próximo estado.
setCount agora é executado de forma assíncrona -> esta função é síncrona, mas depois retorna o resultado. O gancho para setCount irá despachar eventos para atualizar o próximo estado
De onde vem essa função? -> você pode fazer qualquer coisa na função, desde que o parâmetro esteja no estado atual e retorne ao próximo estado.
De onde vem o prevCount? -> será passado quando chamar setCount (é obtido do estado atual).
Quando eu executo isso, o que é colocado em prevCount? -> estado atual de setCount.
=> Exemplo de como passar um valor ou uma chamada de volta para setCount aqui: useState hook, setState function. Acessando o valor do estado anterior