React + useState () + previousState

Sep 11 2020

Sono abbastanza nuovo nel reagire e ho problemi a comprendere il hook useState - o più specificamente l'aspetto del previousState .

Un normale hook useState, e probabilmente l'esempio più comune, ha questo aspetto:

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

Quello che ho capito finora è quanto segue:

  • Chiamo la funzione useState () / Hook? e passare l'argomento dello stato iniziale (initialCount)
  • Ricevo un array che distruggo immediatamente nelle variabili count e setCount (che è la funzione)
  • Con setCount () posso aggiornare lo stato e quindi la variabile count

Fin qui tutto bene, penso ...;)

A volte vedo lo stesso esempio di contatore con prevState (prevCount) che non capisco:

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

Che succede qui? Questa parte non capisco. I miei pensieri finora:

  • In questo caso, in qualche modo accedo al valore di conteggio precedente.
  • setCount si aspetta ora una funzione
  • setCount è ora eseguito in modo asincrono
  • Da dove viene questa funzione?
  • Da dove proviene prevCount?
  • Quando lo eseguo, cosa viene inserito in prevCount?

Capisci la mia confusione? Non sono sicuro di come dovrei inquadrarlo in modo diverso ...

Grazie mille per il tuo aiuto.

Risposte

6 devserkan Sep 11 2020 at 19:15

Prima di tutto, puoi vedere la spiegazione ufficiale qui .

In questo caso, in qualche modo accedo al valore di conteggio precedente.

Non stai accedendo in qualche modo al valore di conteggio precedente. Se usi un aggiornamento funzionale e dai una funzione di callback al setter, ti restituisce lo stato precedente e usi questo valore nella tua funzione di callback.

setCount si aspetta ora una funzione

Poiché fornisci una funzione, può usarla.

setCount è ora eseguito in modo asincrono

In realtà no. Non è una funzione asincrona. Fornisce solo lo stato precedente e lo usi. I setter di stato non sono asincroni, l'aggiornamento dello stato lo è.

Da dove viene questa funzione?

Da dove proviene prevCount?

Già risposto.

Quando lo eseguo, cosa viene inserito in prevCount?

Fornisci quello che vuoi che sia impostato il nuovo stato lì. Nel tuo esempio, vuoi incrementare countdi 1, quindi stai fornendo+ 1

Ecco una spiegazione ingenua per questa logica. Solo un ingenuo. Sto aggiungendo questo per esemplificare la logica di callback, questo non è correlato a 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);

Forse questo esempio sarebbe adatto per imitare la logica di impostazione dello stato di React. Di nuovo, solo un approccio ingenuo.

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

Diamo un'occhiata alla reale implementazione di useState(senza digitazioni):

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

Bene, usa solo useReducerdietro le tende. Imposta lo stato iniziale e utilizza basicStateReducer che è:

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

Come il nostro approccio ingenuo, cerca il tipo di actione si comporta in base a quello. Infine, questo è ciò che useReducer ritorna :

return [workInProgressHook.memoizedState, dispatch];

Quindi, alla fine della giornata, se forniamo una funzione a useState, la prende e poi la esegue sul nostro stato e restituisce il valore.

1 VietDinh Sep 11 2020 at 19:10

Ecco la mia opinione come capisco:

In questo caso, in qualche modo accedo al valore di conteggio precedente. -> setCount controllerà param, se param è un callback richiamerà quella call e passerà lo stato precedente per param. Il risultato della richiamata sarà il prossimo stato.

setCount si aspetta ora una funzione -> sì, la funzione gestisce la logica e restituisce lo stato successivo.

setCount ora viene eseguito in modo asincrono -> questa funzione è sincronizzata ma dopo aver restituito il risultato. L'hook per setCount invierà l'evento per aggiornare lo stato successivo

Da dove viene questa funzione? -> puoi fare qualsiasi cosa in funzione fintanto che param sarà lo stato corrente e restituirà uno stato successivo.

Da dove proviene prevCount? -> verrà passato alla chiamata setCount (viene ottenuto dallo stato corrente).

Quando lo eseguo, cosa viene inserito in prevCount? -> stato corrente di setCount.

=> Esempio di come passare un valore o una chiamata a setCount qui: hook useState, funzione setState. Accesso al valore dello stato precedente