React + useState () + previousState
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
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.
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