Ik ben nieuw bij React, ik heb alleen een vraag over de setState-methode. Laten we zeggen dat we een component hebben:
class MyApp extends React.Component {
state = {
count: 3
};
Increment = () => {
this.setState((prevState) => ({
options: prevState.count + 1)
}));
}
}
dus waarom moeten we prevState gebruiken in de setState-methode? waarom kunnen we niet gewoon doen:
this.setState(() => ({
options: this.state.count + 1)
}));
Antwoord 1, autoriteit 100%
Beide handtekeningen kunnen worden gebruikt, het enige verschil is dat als u uw status moet wijzigen op basis van de vorige status, u this.setState(function)
moet gebruiken, waarmee u een momentopname krijgt (prevState
) van de vorige staat. Maar als de wijziging niet afhankelijk is van een andere eerdere waarde, wordt een kortere versie aanbevolen this.setState({prop: newValue})
this.setState(prevState =>{
return{
...prevState,
counter : prevState.counter +1
}
})
this.setState({counter : 2})
Antwoord 2, autoriteit 65%
class MyApp extends React.Component {
state = {
count: 0
};
Increment = () => {
this.setState(prevState => ({
count: prevState.count + 1
}));
this.setState(prevState => ({
count: prevState.count + 1
}));
this.setState(prevState => ({
count: prevState.count + 1
}));
this.setState(prevState => ({
count: prevState.count + 1
}));
};
IncrementWithoutPrevState = () => {
this.setState(() => ({
count: this.state.count + 1
}));
this.setState(() => ({
count: this.state.count + 1
}));
this.setState(() => ({
count: this.state.count + 1
}));
this.setState(() => ({
count: this.state.count + 1
}));
};
render() {
return (
<div>
<button onClick={this.IncrementWithoutPrevState}>
Increment 4 times without PrevState
</button>
<button onClick={this.Increment}>
Increment 4 times with PrevState
</button>
<h1>Count: {this.state.count}</h1>
</div>
);
}
}
Ik heb zojuist een voorbeeld voor je gemaakt om een idee te geven wat wordt bedoeld met “React may batch multiple setState()…” en waarom we prevState in het bovenstaande scenario moeten gebruiken.
Probeer eerst te radenwat het resultaat moet zijn van count
wanneer u op beide knoppen klikt… Als u denkt dat de count
wordt met 4 verhoogd bij het klikken op beide knoppen, dan is het niet juist;)
Waarom? omdatin de methode IncrementWithoutPrevState
omdat er meerdere setState
-aanroepen zijn, dus React heeft al die aanroepen gegroepeerd en de state
bijgewerkt alleen in de laatste aanroep van setState
in deze methode, dus op het moment van de laatste aanroep van setState
in deze methode is this.state.count
nog niet bijgewerkt en de waarde is nog steeds dezelfde die was voordat de methode IncrementWithoutPrevState
werd ingevoerd, dus de resulterende status bevat count
verhoogd met 1.
Aan de andere kant, als we de Increment
-methode analyseren:
Nogmaals zijn er meerdere setState
oproepen en reageer ze allemaal dat ze allemaal betekent dat de werkelijke toestand zal worden bijgewerkt in de laatste oproep van setState
maar de prevState
Will Bevat altijd de gewijzigde state
in de recente setState
CALL. Als previousState.count
Waarde is al 3 keer verhoogd totdat de laatste oproep van setState
dus de resulterende state
bevat de telwaarde die wordt verhoogd door 4 .
Antwoord 3, Autoriteit 10%
Hier is ISEAWYONE KENNEN ENKEL JUIST: PREVSTATE.COUNTER + 1 .. We kunnen dit ook met staat doen: This.State.Counter + 1. Dit is niet de manier waarop ik denk te gebruiken. Ik heb een probleem in de array wanneer ik in de bestaande staat duwt, waardoor ik me de tweede keer voorkomt, voorkomt het veranderingen
Antwoord 4
Als u een functie meerdere keren belt om de waarde van een staatsobject in een enkele render()
Functie-oproep, gaat de bijgewerkte waarde niet over tussen de verschillende oproepen zonder het prevaluerende mechanisme.
second(){
this.setState({ // no previous or latest old state passed
sec:this.state.sec + 1
}, ()=>{
console.log("Callback value", this.state.sec)
})
}
fiveSecJump(){ // all this 5 call will call together
this.second() // this call found sec = 0 then it will update sec = 0 +1
this.second() // this call found sec = 0 then it will update sec = 0 +1
this.second() // this call found sec = 0 then it will update sec = 0 +1
this.second() // this call found sec = 0 then it will update sec = 0 +1
this.second() // this call found sec = 0 then it will update sec = 0 +1
}
render() {
return (
<div>
<div> Count - {this.state.sec}</div>
<button onClick ={()=>this.fiveSecJump()}>Increment</button>
</div>
)
}
Uiteindelijk is de sec-waarde 1, omdat aanroepen async zijn, niet zoals programmeertaal op hoog niveau zoals c++/c# of java, waar er altijd een hoofdfunctie is die de hoofdthread onderhoudt.
Dus als je de functie fiveSecJump()
goed wilt laten werken, moet je het helpen door er een pijlfunctie aan door te geven. vorigeStaat. prevState is geen trefwoord of lidfunctie, u kunt hier elk woord schrijven, zoals oldState, stackTopState, lastState. Het wordt geconverteerd naar een generieke functie die het gewenste werk zal doen.
class Counter extends Component {
constructor(props){
super(props)
this.state = {
sec:0
}
}
second(){
this.setState(prevState =>({
sec:prevState.sec + 1
}))
}
fiveSecJump(){
this.second() // this call found sec = 0 then it will update sec = 0 +1
this.second() // this call found sec = 1 then it will update sec = 1 +1
this.second() // this call found sec = 2 then it will update sec = 2 +1
this.second() // this call found sec = 3 then it will update sec = 3 +1
this.second() // this call found sec = 4 then it will update sec = 4 +1
}
render() {
return (
<div>
<div> Count - {this.state.sec}</div>
<button onClick ={()=>this.fiveSecJump()}>Increment</button>
</div>
)
}
}
export default Counter
Antwoord 5
//Here is the example to explain both concepts:
import React, { Component } from 'react'
export default class Counter extends Component {
constructor(props) {
super(props);
this.state = { counter: 0 }
}
increment() {
this.setState({counter:this.state.counter+1})
}
increment3() {
this.increment();
this.increment()
this.increment()
}
render() {
return (
<div>
count-{this.state.counter}
<div>
<button onClick={() => this.increment3()}>Increment</button>
</div>
</div>
)
}
}
Als we in dit scenario op de knop Verhogenklikken, wordt de uitvoer in de gebruikersinterface weergegeven als count-0en niet count-3omdat react alle statusaanroepen in een enkele statusaanroep groepeert en niet de bijgewerkte waarde over elke verhoogde aanroep draagt. Als ik de waarde wil bijwerken op basis van de vorige waarde, gebruik dan onderstaande code.
import React, { Component } from 'react'
export default class Counter extends Component {
constructor(props) {
super(props);
this.state = { counter: 0 }
}
increment() {
this.setState((prevState=>({counter:prevState.counter+1})))
}
incremental() {
this.increment();
this.increment()
this.increment()
}
render() {
return (
<div>
count-{this.state.counter}
<div>
<button onClick={() => this.incremental()}>Increment</button>
</div>
</div>
)
}
}
In dit scenario is de uitvoer count-3en niet count-0
Antwoord 6
@samee’s antwoord was geweldig en heeft me geholpen. Ik wilde dit onderwerp nieuw leven inblazen om React Function Components aan te pakken, simpelweg omdat ik dat momenteel bestudeer.
Het volgende is een voorbeeld van waarom u prevState zou willen gebruiken als de nieuwe status wordt berekend met de vorige status.
function App() {
const [developer, setDeveloper] = useState({
yearsExp: 0,
});
function handleYearsExp() {
setDeveloper((prevState) => ({
yearsExp: prevState.yearsExp + 1, //increments by 1
}));
setDeveloper((prevState) => ({
yearsExp: prevState.yearsExp + 1, //increments by another 1
}));
}
return (
<>
<button onClick={handleYearsExp}>Increment Years</button> {/* will increment by 2 */}
<p>
I am learning ReactJS and I have {developer.yearsExp} years experience
</p>
</>
);
}
Hier is de code zonder de functie prevState
die is doorgegeven aan setState
. Merk op dat de eerste functie setState
in wezen wordt genegeerd.
function App() {
const [developer, setDeveloper] = useState({
yearsExp: 0,
});
function handleYearsExp() {
setDeveloper({
yearsExp: developer.yearsExp + 1, // is ignored
});
setDeveloper({
yearsExp: developer.yearsExp + 1, //increments by 1
});
}
return (
<>
<button onClick={handleYearsExp}>Increment Years</button> {/* will only increment by 1 */}
<p>
I am learning ReactJS and I have {developer.yearsExp} years experience
</p>
</>
);
}
Referenties: