React
Stan w reakcji
Szukaj…
Stan podstawowy
Składniki State in React są niezbędne do zarządzania danymi w aplikacji i przekazywania ich. Jest reprezentowany jako obiekt JavaScript i ma zakres na poziomie komponentu , można go traktować jako prywatne dane komponentu.
W poniższym przykładzie definiujemy stan początkowy w funkcji constructor
naszego komponentu i wykorzystujemy go w funkcji 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>
);
}
}
setState ()
Podstawowym sposobem dokonywania aktualizacji interfejsu użytkownika do aplikacji React jest wywołanie funkcji setState()
. Ta funkcja wykona płytkie scalenie między nowym stanem, który podajesz, a poprzednim stanem, i uruchomi ponowne renderowanie twojego komponentu i wszystkich decedentów.
Parametry
-
updater
: Może to być obiekt z wieloma parami klucz-wartość, który powinien zostać scalony ze stanem, lub funkcja zwracająca taki obiekt. -
callback (optional)
: funkcja, która zostanie wykonana posetState()
wykonaniusetState()
. Ponieważ React nie gwarantuje, że wywołaniasetState()
mają charakter atomowy, może to czasem być przydatne, jeśli chcesz wykonać jakąś akcję posetState()
żesetState()
został pomyślnie wykonany.
Stosowanie:
Metoda setState
akceptuje argument updater
który może być albo obiektem z wieloma parami klucz-wartość, które powinny zostać scalone w stan, lub funkcją, która zwraca taki obiekt obliczony z prevState
i props
.
Użycie setState()
z Object jako 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>
);
}
}
Użycie setState()
z funkcją jako 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
};
});
Może to być bezpieczniejsze niż użycie argumentu obiektowego, w którym używanych jest wiele wywołań setState()
, ponieważ wiele wywołań może być grupowanych razem przez React i wykonywane jednocześnie, i jest to preferowane podejście przy użyciu bieżących rekwizytów do ustawienia stanu.
this.setState({ counter: this.state.counter + 1 });
this.setState({ counter: this.state.counter + 1 });
this.setState({ counter: this.state.counter + 1 });
Wywołania te mogą być grupowane razem przez React za pomocą Object.assign()
, w wyniku czego licznik jest zwiększany o 1 zamiast 3.
Podejście funkcjonalne można również wykorzystać do przeniesienia logiki ustawiania stanu poza komponenty. Pozwala to na izolację i ponowne wykorzystanie logiki stanu.
// Outside of component class, potentially in another file/module
function incrementCounter(previousState, currentProps) {
return {
counter: previousState.counter + 1
};
}
// Within component
this.setState(incrementCounter);
Wywołanie setState()
z Object i funkcją zwrotną
//
// 'Hi There' will be logged to the console after setState completes
//
this.setState({ name: 'John Doe' }, console.log('Hi there'));
Wspólne antipattern
Nie powinieneś zapisywać props
do state
. Jest uważany za anty-wzór . Na przykład:
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>
)
}
}
url
prop jest zapisywany w state
a następnie modyfikowany. Zamiast tego wybierz zapisanie zmian do stanu, a następnie zbuduj pełną ścieżkę, używając zarówno state
jak i 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>
)
}
}
Wynika to z faktu, że w aplikacji React chcemy mieć jedno źródło prawdy - tj. Za wszystkie dane odpowiedzialny jest jeden element i tylko jeden element. Obowiązkiem tego komponentu jest przechowywanie danych w jego stanie i przekazywanie danych do innych komponentów za pomocą rekwizytów.
W pierwszym przykładzie zarówno klasa MyComponent, jak i jej rodzic utrzymują „url” w swoim stanie. Jeśli zaktualizujemy state.url w MyComponent, zmiany te nie zostaną odzwierciedlone w obiekcie nadrzędnym. Straciliśmy nasze jedyne źródło prawdy i coraz trudniej jest śledzić przepływ danych za pośrednictwem naszej aplikacji. Porównaj to z drugim przykładem - adres URL jest utrzymywany tylko w stanie komponentu nadrzędnego i wykorzystywany jako rekwizyt w MyComponent - dlatego utrzymujemy jedno źródło prawdy.
Stan, zdarzenia i kontrolowane elementy sterujące
Oto przykład komponentu React z „zarządzanym” polem wejściowym. Ilekroć zmienia się wartość pola wejściowego, wywoływana jest procedura obsługi zdarzeń, która aktualizuje stan komponentu o nową wartość pola wejściowego. Wywołanie setState
w setState
obsługi zdarzeń wyzwoli wywołanie w celu render
aktualizacji komponentu w domenie.
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'));
Bardzo ważne jest zwrócenie uwagi na zachowanie środowiska wykonawczego. Za każdym razem, gdy użytkownik zmienia wartość w polu wprowadzania
-
handleChange
zostanie wywołany i tak - zostanie
setState
i tak dalej -
render
zostanie wywołany
Pop quiz, po wpisaniu znaku w polu wprowadzania, które elementy DOM zmieniają się
- wszystkie z nich - div najwyższego poziomu, legenda, wejście, h1
- tylko wejście i h1
- nic
- co to jest DOM?
Możesz eksperymentować z tym więcej tutaj, aby znaleźć odpowiedź