React` setState ‘
React-componenten kunnen, en hebben vaak, status. Status kan van alles zijn, maar denk aan dingen als of een gebruiker is ingelogd of niet en het weergeven van de juiste gebruikersnaam op basis van welke account actief is. Of een reeks van blog posts. Of als een modaal open is of niet en welk tabblad erin actief is.
reageer componenten met status render UI gebaseerd op die status. Wanneer de toestand van componenten verandert, doet de component UI.
dat maakt het belangrijk om te begrijpen wanneer en hoe je de status van je component moet veranderen. Aan het einde van deze handleiding zou je moeten weten hoe setState
werkt, en in staat zijn om gemeenschappelijke valkuilen te vermijden die velen van ons raken wanneer het leren reageert.
werking van ‘setState ()’
setState()
is de enige legitieme manier om de status na de initiële status-instelling bij te werken. Laten we zeggen dat we een zoekcomponent hebben en de zoekterm willen weergeven die een gebruiker indient.
Hier is de instelling:
import React, { Component } from 'react'class Search extends Component { constructor(props) { super(props) state = { searchTerm: '' } }}
We geven een lege tekenreeks door als waarde en om de status van searchTerm
bij te werken, moeten we setState()
aanroepen.
setState({ searchTerm: event.target.value })
Hier geven we een object door aan setState()
. Het object bevat het deel van de status dat we willen bijwerken, wat in dit geval de waarde is van searchTerm
. React neemt deze waarde en voegt deze samen in het object dat het nodig heeft. Het is ongeveer zoals de Search
component vraagt wat het moet gebruiken voor de waarde van searchTerm
en setState()
antwoordt met een antwoord.
Dit is eigenlijk de aftrap van een proces dat reconciliatie van aanroepen reageert. Het reconciliatieproces is de manier waarop React de DOM updates uitvoert, door wijzigingen aan te brengen aan de component op basis van de statuswijziging. Wanneer de aanvraag voor setState()
wordt geactiveerd, maakt React een nieuwe boom aan met de reactieve elementen in de component (samen met de bijgewerkte status). Deze boomstructuur wordt gebruikt om erachter te komen hoe de UI van het Search
component moet veranderen als reactie op de statusverandering door het te vergelijken met de elementen van de vorige boom. React weet welke wijzigingen te implementeren en zal alleen de delen van de DOM waar nodig bijwerken. Daarom is reageren snel.
dat klinkt als veel, maar om de stroom samen te vatten:
- We hebben een search-onderdeel dat geeft een zoek term
- Die zoekterm is momenteel leeg
- De gebruiker een zoekterm
- dit begrip wordt opgevangen en opgeslagen
setState
waarde - Afstemming plaatsvindt en Reageren merkt de verandering in waarde
- Reageren instrueert de zoek-component voor het bijwerken van de waarde van de zoekterm is samengevoegd
Het afstemmingsproces niet noodzakelijkerwijs het gehele boom, behalve in een situatie waar de wortel van de boom wordt gewijzigd zoals dit:
// old<div> <Search /></div>// new<span> <Search /></span>
alle <div>
tags worden <span>
tags en de gehele component boom zal als resultaat worden bijgewerkt.
de vuistregel is om de toestand nooit direct te muteren. Gebruik altijd setState()
om de status te wijzigen. Het wijzigen van de status direct, zoals het fragment hieronder zal niet leiden tot het onderdeel opnieuw te renderen.
// do not do thisthis.state = { searchTerm: event.target.value}
een functie doorgeven aan `setState()`
om dit idee verder aan te tonen, maken we een eenvoudige teller die toeneemt en afneemt bij klikken.
zie de pen setState Pen van Kingsley Silas Chijioke (@kinsomicrote) op CodePen.
laten we de component registreren en de opmaak voor de UI definiëren:
class App extends React.Component {state = { count: 0 }handleIncrement = () => { this.setState({ count: this.state.count + 1 })}handleDecrement = () => { this.setState({ count: this.state.count - 1 })} render() { return ( <div> <div> {this.state.count} </div> <button onClick={this.handleIncrement}>Increment by 1</button> <button onClick={this.handleDecrement}>Decrement by 1</button> </div> ) }}
Op dit punt verhoogt of verlaagt de teller de telling met 1 bij elke klik.
maar wat als we in plaats daarvan willen verhogen of verlagen met 3? We zouden kunnen proberen om setState()
drie keer aan te roepen in de handleDecrement
en handleIncrement
functies zoals deze:
handleIncrement = () => { this.setState({ count: this.state.count + 1 }) this.setState({ count: this.state.count + 1 }) this.setState({ count: this.state.count + 1 })}handleDecrement = () => { this.setState({ count: this.state.count - 1 }) this.setState({ count: this.state.count - 1 }) this.setState({ count: this.state.count - 1 })}
Als u thuis mee aan het coderen bent, zult u misschien verbaasd zijn dat dit niet werkt.
het bovenstaande codefragment is gelijk aan:
Object.assign( {}, { count: this.state.count + 1 }, { count: this.state.count + 1 }, { count: this.state.count + 1 },)
Object.assign()
wordt gebruikt om gegevens van een bronobject naar een doelobject te kopiëren. Als de gegevens die worden gekopieerd van de bron naar het doel allemaal dezelfde sleutels hebben, zoals in ons voorbeeld, wint het laatste object. Hier is een eenvoudigere versie van hoe Object.assign()
werkt;
let count = 3const object = Object.assign({}, {count: count + 1}, {count: count + 2}, {count: count + 3});console.log(object);// output: Object { count: 6 }
dus in plaats van de aanroep drie keer gebeurt, gebeurt het maar één keer. Dit kan worden opgelost door een functie door te geven aan setState()
. Net zoals u objecten doorgeeft aan setState()
, kunt u ook functies doorgeven, en dat is de uitweg uit de bovenstaande situatie.
als we de functie handleIncrement
bewerken om er zo uit te zien:
handleIncrement = () => { this.setState((prevState) => ({ count: prevState.count + 1 })) this.setState((prevState) => ({ count: prevState.count + 1 })) this.setState((prevState) => ({ count: prevState.count + 1 }))}
…kunnen we nu het aantal drie keer verhogen met één klik.
in dit geval, in plaats van het samenvoegen, React wachtrijen de functie aanroepen in de volgorde waarin ze worden gemaakt en updates de volledige status degenen die het is gedaan. Hiermee wordt de stand van telling bijgewerkt naar 3 in plaats van 1.
toegang tot de vorige status met behulp van Updater
bij het bouwen van React-toepassingen, zijn er momenten waarop u de status wilt berekenen op basis van de vorige status van het onderdeel. U kunt this.state
niet altijd vertrouwen om de juiste status te behouden onmiddellijk na het aanroepen van setState()
, omdat deze altijd gelijk is aan de status die op het scherm wordt weergegeven.
laten we teruggaan naar ons teller voorbeeld om te zien hoe dit werkt. Laten we zeggen dat we een functie hebben die ons aantal met 1 verlaagt. Deze functie ziet er zo uit:
changeCount = () => { this.setState({ count: this.state.count - 1})}
wat we willen is de mogelijkheid om te decrementeren met 3. De functie changeCount()
wordt drie keer aangeroepen in een functie die de click event afhandelt, zoals dit.
handleDecrement = () => { this.changeCount() this.changeCount() this.changeCount()}
elke keer dat op de knop om te decrementeren wordt geklikt, zal het aantal verminderen met 1 in plaats van 3. Dit komt omdat de this.state.count
niet wordt bijgewerkt totdat de component opnieuw is gerenderd. De oplossing is om een updater te gebruiken. Met een updater hebt u toegang tot de huidige status en kunt u deze onmiddellijk gebruiken om andere items bij te werken. Dus de functie changeCount()
ziet er zo uit.
nu zijn we niet afhankelijk van het resultaat van this.state
. De statussen van count
zijn op elkaar gebouwd zodat we toegang hebben tot de juiste status die bij elke aanroep verandert naar changeCount()
.
setState()
moet asynchroon worden behandeld — met andere woorden, verwacht niet altijd dat de status is veranderd na het aanroepen van setState()
.
inpakken
Bij het werken met setState()
, dit zijn de belangrijkste dingen die je moet weten:
- de Update van een component staat moet worden gedaan met behulp van
setState()
- Je kan een object of een functie
setState()
- Pas een functie als je kunt om de update staat meerdere keren
- niet afhankelijk zijn van deze.geef onmiddellijk na het aanroepen van
setState()
op en gebruik in plaats daarvan de updater-functie.