React
Состояние в действии
Поиск…
Основное состояние
Компоненты State in React необходимы для управления и передачи данных в вашем приложении. Он представлен как объект JavaScript и обладает областью уровня компонента , его можно рассматривать как частные данные вашего компонента.
В приведенном ниже примере мы определяем некоторое начальное состояние в constructor
функции нашего компонента и используем его в функции 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 ()
Основной способ, которым вы делаете обновления пользовательского интерфейса для своих приложений React, - это вызов функции setState()
. Эта функция будет выполнять мелкое слияние между новым состоянием, которое вы предоставляете, и предыдущим состоянием, и вызовет повторную визуализацию вашего компонента и всех его дециентов.
параметры
-
updater
: Это может быть объект с несколькими парами ключ-значение, которые должны быть объединены в состояние или функцию, возвращающую такой объект. -
callback (optional)
: функция, которая будет выполнена после того, какsetState()
выполнена успешно. Из-за того, чтоsetState()
не гарантируется, что React является атомарным, иногда это может быть полезно, если вы хотите выполнить какое-либо действие после того, как выsetState()
чтоsetState()
успешно выполнен.
Использование:
setState
метод принимает программу updater
аргумента , который может быть либо объектом с рядом ключом-значением-пар , которые должны быть объединены в состояние, или функцией , которая возвращает такой объект , вычисленный из prevState
и props
.
Использование setState()
с объектом как средство 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>
);
}
}
Использование setState()
с функцией в качестве средства 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
};
});
Это может быть безопаснее, чем использование аргумента объекта, в котором используются множественные вызовы для setState()
, поскольку несколько вызовов могут быть собраны вместе с помощью React и выполняться сразу, и это предпочтительный подход при использовании текущих реквизитов для установки состояния.
this.setState({ counter: this.state.counter + 1 });
this.setState({ counter: this.state.counter + 1 });
this.setState({ counter: this.state.counter + 1 });
Эти вызовы могут быть объединены путем React с использованием Object.assign()
, в результате чего счетчик увеличивается на 1, а не на 3.
Функциональный подход также может использоваться для перемещения логики настройки состояния вне компонентов. Это позволяет изолировать и повторно использовать логику состояния.
// Outside of component class, potentially in another file/module
function incrementCounter(previousState, currentProps) {
return {
counter: previousState.counter + 1
};
}
// Within component
this.setState(incrementCounter);
Вызов функции setState()
с объектом и функцией обратного вызова
//
// 'Hi There' will be logged to the console after setState completes
//
this.setState({ name: 'John Doe' }, console.log('Hi there'));
Общий антипаттерн
Вы не должны сохранять props
в state
. Он считается анти-шаблоном . Например:
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 сохраняется в state
а затем изменен. Вместо этого выберите сохранение изменений в состоянии, а затем постройте полный путь, используя как state
и 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>
)
}
}
Это связано с тем, что в приложении React мы хотим иметь единственный источник правды - т.е. все данные являются ответственностью одного единственного компонента и только одного компонента. Ответственность этого компонента заключается в сохранении данных в его состоянии и распространении данных на другие компоненты через реквизиты.
В первом примере как класс MyComponent, так и его родительский элемент поддерживают «url» в своем состоянии. Если мы обновим state.url в MyComponent, эти изменения не будут отражены в родительском. Мы потеряли наш единственный источник правды, и становится все труднее отслеживать поток данных через наше приложение. Сравните это со вторым примером - url поддерживается только в состоянии родительского компонента и используется в качестве опоры в MyComponent - поэтому мы сохраняем единый источник правды.
Состояние, события и управляемые элементы управления
Вот пример компонента React с «управляемым» полем ввода. Всякий раз, когда изменяется значение поля ввода, вызывается обработчик событий, который обновляет состояние компонента с новым значением поля ввода. Вызов setState
в обработчике событий вызовет вызов для render
обновления компонента в 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'));
Очень важно отметить поведение во время работы. Каждый раз, когда пользователь меняет значение в поле ввода
-
handleChange
будет вызван и так -
setState
будет вызываться и так -
render
будет вызван
Pop quiz, после ввода символа в поле ввода, с помощью которого элементы DOM изменяются
- все из них - верхний уровень div, легенда, вход, h1
- только вход и h1
- ничего такого
- Что такое DOM?
Вы можете поэкспериментировать с этим больше здесь, чтобы найти ответ