React
State in React
Sök…
Grundtillstånd
State in React-komponenter är viktigt för att hantera och kommunicera data i din applikation. Det representeras som ett JavaScript-objekt och har komponentnivåomfång, det kan ses som din privata data för din komponent.
I exemplet nedan definierar vi ett visst initialt tillstånd i constructor
för vår komponent och använder det i render
.
class ExampleComponent extends React.Component {
constructor(props){
super(props);
// Set-up our initial state
this.state = {
greeting: 'Hiya Buddy!'
};
}
render() {
// We can access the greeting property through this.state
return(
<div>{this.state.greeting}</div>
);
}
}
sets ()
Det primära sättet att du gör UI-uppdateringar för dina React-applikationer är genom ett samtal till setState()
. Denna funktion kommer att utföra en grunt sammanslagning mellan det nya tillstånd som du tillhandahåller och det tidigare tillståndet och kommer att utlösa en återgivning av din komponent och alla decedents.
parametrar
-
updater
: Det kan vara ett objekt med ett antal nyckelvärdespar som ska slås samman till tillståndet eller en funktion som returnerar ett sådant objekt. -
callback (optional)
: en funktion som kommer attsetState()
efter attsetState()
har genomförts framgångsrikt. På grund av det faktum att samtal tillsetState()
inte garanteras av React att vara atomiska, kan detta ibland vara användbart om du vill utföra några åtgärder efter att du ärsetState()
attsetState()
har genomförts framgångsrikt.
Användande:
setState
metoden accepterar ett updater
som antingen kan vara ett objekt med ett antal nyckelvärden-par som ska slås samman i tillståndet, eller en funktion som returnerar ett sådant objekt beräknat från prevState
och props
.
Använda setState()
med ett objekt som updater
//
// An example ES6 style component, updating the state on a simple button click.
// Also demonstrates where the state can be set directly and where setState should be used.
//
class Greeting extends React.Component {
constructor(props) {
super(props);
this.click = this.click.bind(this);
// Set initial state (ONLY ALLOWED IN CONSTRUCTOR)
this.state = {
greeting: 'Hello!'
};
}
click(e) {
this.setState({
greeting: 'Hello World!'
});
}
render() {
return(
<div>
<p>{this.state.greeting}</p>
<button onClick={this.click}>Click me</button>
</div>
);
}
}
Använda setState()
med en funktion som updater
//
// This is most often used when you want to check or make use
// of previous state before updating any values.
//
this.setState(function(previousState, currentProps) {
return {
counter: previousState.counter + 1
};
});
Detta kan vara säkrare än att använda ett objektargument där flera samtal till setState()
används, eftersom flera samtal kan samlas av React och exekveras samtidigt, och är den föredragna metoden när man använder nuvarande rekvisita för att ställa in tillstånd.
this.setState({ counter: this.state.counter + 1 });
this.setState({ counter: this.state.counter + 1 });
this.setState({ counter: this.state.counter + 1 });
Dessa samtal kan samlas samman av React med hjälp av Object.assign()
, vilket resulterar i att räknaren ökas med 1 snarare än 3.
Det funktionella tillvägagångssättet kan också användas för att flytta tillståndsinställningslogik utanför komponenterna. Detta möjliggör isolering och återanvändning av tillståndslogik.
// Outside of component class, potentially in another file/module
function incrementCounter(previousState, currentProps) {
return {
counter: previousState.counter + 1
};
}
// Within component
this.setState(incrementCounter);
Ringa setState()
med ett objekt och en återuppringningsfunktion
//
// 'Hi There' will be logged to the console after setState completes
//
this.setState({ name: 'John Doe' }, console.log('Hi there'));
Vanliga antipattern
Du bör inte spara props
i state
. Det anses vara ett antimönster . Till exempel:
export default class MyComponent extends React.Component {
constructor() {
super();
this.state = {
url: ''
}
this.onChange = this.onChange.bind(this);
}
onChange(e) {
this.setState({
url: this.props.url + '/days=?' + e.target.value
});
}
componentWillMount() {
this.setState({url: this.props.url});
}
render() {
return (
<div>
<input defaultValue={2} onChange={this.onChange} />
URL: {this.state.url}
</div>
)
}
}
Prop- url
sparas i state
och ändras sedan. Välj istället för att spara ändringarna i ett tillstånd och bygg sedan upp hela sökvägen med både state
och props
:
export default class MyComponent extends React.Component {
constructor() {
super();
this.state = {
days: ''
}
this.onChange = this.onChange.bind(this);
}
onChange(e) {
this.setState({
days: e.target.value
});
}
render() {
return (
<div>
<input defaultValue={2} onChange={this.onChange} />
URL: {this.props.url + '/days?=' + this.state.days}
</div>
)
}
}
Detta beror på att vi i en React-applikation vill ha en enda sanningskälla - dvs all data är ansvaret för en enda komponent och bara en komponent. Det är denna komponents ansvar att lagra informationen i dess tillstånd och distribuera informationen till andra komponenter via rekvisita.
I det första exemplet upprätthåller både MyComponent-klassen och dess överordnade "url" i sitt tillstånd. Om vi uppdaterar state.url i MyComponent återspeglas inte dessa förändringar i överordnade. Vi har tappat vår enda sanningskälla och det blir allt svårare att spåra flödet av data genom vår applikation. Kontrast detta med det andra exemplet - url upprätthålls endast i tillståndet för moderkomponenten och används som en rekvisita i MyComponent - vi har därför en enda källa till sanning.
Tillstånd, händelser och hanterade kontroller
Här är ett exempel på en React-komponent med ett "hanterat" inmatningsfält. När värdet på inmatningsfältet ändras kallas en händelsehanterare som uppdaterar komponentens tillstånd med det nya värdet för inmatningsfältet. Uppmaningen till setState
i händelsehanteraren kommer att utlösa en uppmaning att render
uppdatera komponent i dom.
import React from 'react';
import {render} from 'react-dom';
class ManagedControlDemo extends React.Component {
constructor(props){
super(props);
this.state = {message: ""};
}
handleChange(e){
this.setState({message: e.target.value});
}
render() {
return (
<div>
<legend>Type something here</legend>
<input
onChange={this.handleChange.bind(this)}
value={this.state.message}
autoFocus />
<h1>{this.state.message}</h1>
</div>
);
}
}
render(<ManagedControlDemo/>, document.querySelector('#app'));
Det är mycket viktigt att notera körbeteendet. Varje gång en användare ändrar värdet i inmatningsfältet
-
handleChange
kommer att kallas och så -
setState
kommer att kallas och så -
render
kommer att kallas
Popquiz, när du har skrivit ett tecken i inmatningsfältet, vilka DOM-element ändras
- alla dessa - toppnivån div, legend, input, h1
- endast ingången och h1
- ingenting
- vad är en DOM?
Du kan experimentera med det här här för att hitta svaret