React + useState () + previousState

Sep 11 2020

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

6 devserkan Sep 11 2020 at 19:15

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.

1 VietDinh Sep 11 2020 at 19:10

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