React + useState () + previousState

Sep 11 2020

Jestem całkiem nowy, jeśli chodzi o reakcję i mam problemy ze zrozumieniem hooka useState - a dokładniej aspektu poprzedniego stanu .

Normalny hook useState i prawdopodobnie najczęstszy przykład wygląda następująco:

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

To, co do tej pory rozumiem, jest następujące:

  • Wywołuję funkcję useState () / hook? i przekaż argument początkowego stanu (initialCount)
  • Otrzymuję tablicę, którą natychmiast niszczę na liczbę zmiennych i setCount (czyli funkcję)
  • Dzięki setCount () mogę zaktualizować stan, a tym samym zmienną count

Jak na razie dobrze, myślę ...;)

Czasami widzę ten sam przykład licznika z prevState (prevCount), którego nie rozumiem:

<button onClick={() => setCount(prevCount => prevCount -1)}>-</button>

co się tutaj stało? Tej części nie rozumiem. Moje dotychczasowe przemyślenia:

  • W tym przypadku w jakiś sposób uzyskuję dostęp do poprzedniej wartości licznika.
  • setCount oczekuje teraz funkcji
  • setCount działa teraz asynchronicznie
  • Skąd pochodzi ta funkcja?
  • Skąd pochodzi prevCount?
  • Po uruchomieniu tego, co jest umieszczane w prevCount?

Czy rozumiesz moje zmieszanie? Nie jestem pewien, jak mam to inaczej oprawić ...

Bardzo ci dziękuje za pomoc.

Odpowiedzi

6 devserkan Sep 11 2020 at 19:15

Po pierwsze, możesz zobaczyć tutaj oficjalne wyjaśnienie .

W tym przypadku w jakiś sposób uzyskuję dostęp do poprzedniej wartości licznika.

W jakiś sposób nie uzyskujesz dostępu do poprzedniej wartości licznika. Jeśli używasz aktualizacji funkcjonalnej i przekazujesz setterowi funkcję zwrotną, zwraca ona poprzedni stan i używasz tej wartości w funkcji wywołania zwrotnego.

setCount oczekuje teraz funkcji

Ponieważ zapewniasz funkcję, może jej używać.

setCount działa teraz asynchronicznie

Właściwie nie. Nie jest to funkcja asynchroniczna. Po prostu zapewnia poprzedni stan i używasz go. Metody ustawiające stan nie są asynchroniczne, aktualizacja stanu jest.

Skąd pochodzi ta funkcja?

Skąd pochodzi prevCount?

Już odpowiedziałem.

Po uruchomieniu tego, co jest umieszczane w prevCount?

Podajesz, jaki chcesz ustawić tam nowy stan. W twoim przykładzie chcesz zwiększyć counto 1, więc podajesz+ 1

Oto naiwne wyjaśnienie tej logiki. Po prostu naiwny. Dodam to, aby zilustrować logikę wywołania zwrotnego, nie jest to związane z ReactemsetState.

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

Może ten przykład byłby odpowiedni do naśladowania logiki ustawiania stanu Reacta. Znowu tylko naiwne podejście.

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

Wygląd Spójrzmy prawdzie w realnej realizacji od useState(bez typowania):

export function useState(initialState) {
  return useReducer(
    basicStateReducer,
    // useReducer has a special case to support lazy useState initializers
    initialState
  );
}

Cóż, po prostu używa useReducerza zasłonami. Ustawia stan początkowy i używa basicStateReducer, który jest:

function basicStateReducer(state, action) {
  return typeof action === "function" ? action(state) : action;
}

Podobnie jak nasze naiwne podejście, szuka typu actioni zachowuje się zgodnie z tym. Wreszcie to, co useReducer zwraca :

return [workInProgressHook.memoizedState, dispatch];

Więc na koniec dnia, jeśli dostarczymy funkcję useState, pobiera ją, a następnie uruchamia w naszym stanie i zwraca wartość z powrotem.

1 VietDinh Sep 11 2020 at 19:10

Oto moja opinia, jak rozumiem:

W tym przypadku w jakiś sposób uzyskuję dostęp do poprzedniej wartości licznika. -> setCount sprawdzi parametr, jeśli parametr jest wywołaniem zwrotnym, wywoła to oddzwonienie i przekaże poprzedni stan dla parametru. Rezultatem oddzwonienia będzie następny stan.

setCount oczekuje teraz funkcji -> tak, funkcja obsługuje logikę i zwraca następny stan.

setCount jest teraz uruchamiany asynchronicznie -> ta funkcja jest synchronizowana, ale po jej zakończeniu zwraca wynik. Haczyk dla setCount wyśle ​​zdarzenie, aby zaktualizować następny stan

Skąd pochodzi ta funkcja? -> możesz zrobić wszystko w funkcji, o ile param będzie aktualnym stanem i zwróci następny stan.

Skąd pochodzi prevCount? -> zostanie przekazane przy wywołaniu setCount (pobiera z bieżącego stanu).

Po uruchomieniu tego, co jest umieszczane w prevCount? -> aktualny stan setCount.

=> Przykład przekazywania wartości lub wywołania zwrotnego do setCount tutaj: hook useState, funkcja setState. Dostęp do wartości poprzedniego stanu