Reagire setState non aggiornandosi immediatamente

Sto lavorando ad un’applicazione todo. Questa è una versione molto semplificata del codice offendente. Ho una casella di controllo:

Writing Item

Ecco la funzione che chiama la casella di controllo:

 checkPencil(){ this.setState({ pencil:!this.state.pencil, }); this.props.updateItem(this.state); } 

updateItem è una funzione mappata su Dispatch to Redux

 function mapDispatchToProps(dispatch){ return bindActionCreators({ updateItem}, dispatch); } 

Il mio problema è che quando chiamo l’azione updateItem e console.log lo stato, è sempre 1 passo indietro. Se la casella di spunta è deselezionata e non è vera, ottengo comunque lo stato di true passato alla funzione updateItem. Devo chiamare un’altra funzione per forzare lo stato ad aggiornare?

Dovresti invocare la tua seconda funzione come callback per setState, in quanto setState avviene in modo asincrono. Qualcosa di simile a:

 this.setState({pencil:!this.state.pencil}, myFunction) 

Tuttavia nel tuo caso, dal momento che vuoi che quella funzione chiamata con un parametro tu debba avere un po ‘più di creatività, e magari creare la tua funzione che chiama la funzione negli oggetti di scena:

 myFunction = () => { this.props.updateItem(this.state) } 

Combina quelli insieme e dovrebbe funzionare.

La chiamata a setState() in React è asincrona, per vari motivi (principalmente prestazioni). Sotto le copertine, React eseguirà il batch di più chiamate a setState() in una singola mutazione di stato, quindi setState() il rendering del componente una volta sola, anziché setState() re-rendering per ogni modifica di stato.

Fortunatamente, la soluzione è piuttosto semplice: setState accetta un parametro di callback:

 checkPencil(){ this.setState({ pencil:!this.state.pencil, }, function () { this.props.updateItem(this.state); }.bind(this)); } 

Quando si aggiorna lo stato utilizzando una proprietà dello stato corrente, la documentazione di React consiglia di utilizzare la versione di chiamata di funzione di setState anziché dell’object.

Quindi setState((state, props) => {...}) invece di setState(object) .

La ragione è che setState è più una richiesta di cambiamento da parte dello stato piuttosto che un cambiamento immediato. setState batch quelle chiamate setState per il miglioramento delle prestazioni.

Significa che la proprietà dello stato che stai verificando potrebbe non essere stabile. Questo è un potenziale trabocchetto di cui essere a conoscenza.

Per maggiori informazioni consultare la documentazione qui: https://facebook.github.io/react/docs/react-component.html#setstate


Per rispondere alla tua domanda, lo farei.

 checkPencil(){ this.setState((prevState) => { return { pencil: !prevState.pencil }; }, () => { this.props.updateItem(this.state) }); } 

È perché accade in modo asincrono , quindi significa che in quel momento potrebbe non essere ancora aggiornato …

Secondo la documentazione di React v.16, è necessario utilizzare una seconda forma di setState() che accetta una funzione piuttosto che un object:

Gli aggiornamenti di stato possono essere asincroni

React può eseguire il batch di più chiamate setState () in un singolo aggiornamento per le prestazioni.

Poiché this.props e this.state possono essere aggiornati in modo asincrono, non si deve fare affidamento sui loro valori per calcolare lo stato successivo.

Ad esempio, questo codice potrebbe non riuscire ad aggiornare il contatore:

 // Wrong this.setState({ counter: this.state.counter + this.props.increment, }); 

Per risolverlo, usa una seconda forma di setState () che accetta una funzione piuttosto che un object. Quella funzione riceverà lo stato precedente come primo argomento e gli oggetti di scena nel momento in cui l’aggiornamento viene applicato come secondo argomento:

 // Correct this.setState((prevState, props) => ({ counter: prevState.counter + props.increment })); 

Ho usato entrambi i suggerimenti di rossipedia e Ben Hare e ho fatto quanto segue:

 checkPencil(){ this.setState({ pencil:!this.state.pencil, }, this.updatingItem); } updatingItem(){ this.props.updateItem(this.state) } 

Ben ha un’ottima risposta su come risolvere il problema immediato, tuttavia vorrei anche evitare di duplicare lo stato

Se uno stato è in redux, la tua casella di controllo dovrebbe leggere il proprio stato da un prop o store invece di tenere traccia dello stato di controllo sia nel proprio componente che nell’archivio globale

Fai qualcosa del genere:

 

Writing Item

La regola generale è che se trovi uno stato che è necessario in più punti, portalo a un genitore comune (non sempre ridondante) per mantenere solo una singola fonte di verità

prova questo

 this.setState({inputvalue: e.target.value}, function () { console.log(this.state.inputvalue); this.showInputError(inputs[0].name); }); 

funzione showInputError per la convalida se si utilizzano moduli

Prima imposta il tuo valore. dopo procedi con i tuoi lavori.

 this.setState({inputvalue: e.target.value}, function () { this._handleSubmit(); }); _handleSubmit() { console.log(this.state.inputvalue); //Do your action }