Сохранение состояния в React Component: особенности работы метода setState

04.09.2018 / oberset

Прежде всего давайте разберемся, что такое внутреннее состояние компонента в React и для чего оно может понадобиться. Состояние компонента – это некие данные, которые сохраняются внутри компонента и влияют на его поведение. К примеру, мы хотим создать компонент, который добавляет к форме элемент управления checkbox. В этом случае нам понадобиться где то хранить текущее значение checked=true/false. Как раз для таких целей лучше всего подходит внутренний state компонента. import React, {Component} from 'react'; class Checkbox extends Component { constructor(props) { super(props); this.state = { checked: false } } handleChange = (event) => { this.setState(({checked}) => ({ checked: !checked })); }; render() { const {checked} = this.state; return ( <input type="checkbox" checked={checked} onChange={this.handleChange} /> ); } }

Компоненты React могут сохранять свое собственное состояние в объекте state, который представляет собой обычный Object, хранящий пары ключ-значение. Единственное место, где можно задавать значения свойств this.state напрямую – это конструктор компонента (если вы используете babel-plugin-transform-class-properties, то можно определить state как свойство в теле класса). В примере выше мы создали в конструкторе объект state со свойством checked и установили начальное значение в false. Далее, в методе render мы используем это значение для отображения текущего состояния элемента. После того, как мы кликнем по checkbox, сработает событие change и новое значение свойства checked запишется в state.

Как вы уже заметили, для записи нового значения свойства объекта state мы вызвали метод setState. Как уже было сказано, модифицировать объект state напрямую можно только в конструкторе, в остальных случаях нужно вызывать метод setState.

Какие параметры принимает setState?

Самый простой способ обновить состояние компонента - это передать в метод setState объект с новыми значениями, которые нужно записать в state: setState({ checked: true, value: 1 });

Если нужно вычислить новое значение на основе текущего, то вместо объекта в метод setState можно передать функцию: setState((currentState) => ({ checked: !currentState.checked, value: 1 })); Функция в качестве параметра получает текущий объект state, значения которого можно использовать для формирования новых значений. Этот вариант вызова setState более предпочтительный.

Вторым параметром setState принимает функцию, которая вызовется после обновления состояния: setState((state) => ({ checked: !state.checked }), () => { console.log('Component updated!'); }); Этот параметр не является обязательным и редко используется, вместо него лучше использовать метод componentDidUpdate.

Вызов setState асинхронный

Какое значение выведется в консоль после вызова setState? // this.state = { value: 0 }; setState({value: 1}); console.log(this.state.value); // 0 На первый взгляд это может показаться странным, но значение value, которое выводится в консоль не изменилось после вызова setState. Причина в том, что setState работает асинхронно и не изменяет state в текущем digist-цикле.

Какое значение в итоге запишется в state? // this.state = { value: 0 }; setState({value: this.state.value + 1}); setState({value: this.state.value + 1}); setState({value: this.state.value + 1}); console.log(this.state.value); // 0 Рассмотрев предыдущий пример, нетрудно догадаться, что после всех вызовов setState в this.state попадет {value: 1}. React объединяет объекты, переданные в каждом вызове setState. Значение this.state.value в текущем digist-цикле не изменяется, поэтому мы получим value = 0 + 1 во всех 3 вызовах. В консоль при этом по-прежнему выведется значение 0. componentDidUpdate() { console.log(this.state.value); // 1 }

Все меняется, если передавать в setState функцию вместо объекта: // this.state = { value: 0 }; this.setState((state) => ({ value: state.value + 1})); this.setState((state) => ({ value: state.value + 1})); this.setState((state) => ({ value: state.value + 1})); В этом случае this.state.value будет равным 3, как и ожидалось. Если новое значение в state вычисляется на основе текущего состояния, всегда передавайте в setState функцию, а не объект. Почему для обновления состояния лучше передавать функцию? Когда React запустит цикл обновления компонента, он будет последовательно выполнять каждую функцию, которую мы передали в setState, сохраняя в state возвращаемое ей значение.

Обновление состояния в асинхронном коде: componentDidMount() { setTimeout(() => { this.setState({value: this.state.value + 1}); this.setState({value: this.state.value + 1}); this.setState({value: this.state.value + 1}); console.log(this.state.value); // 3 }); } Внутри setTimeout метод setState ведет себя по-другому. Этот код выведет в консоль 3, а не 0, как было в примере выше. Нужно учитывать эту особенность при работе с асинхронным кодом.

Как в React повесить DOM-событие на window или document?

Иногда внутри React-компонента требуется повесить DOM-событие на window или document, например, если нужно добавить обработчик события resize или scroll окна браузера.

Композиция с помощью HOC (Higher Order Component) в React

Компонент высшего порядка в React (Higher Order Component или сокращенно HOC) – это простая javascript-функция, которая принимает на вход один или несколько компонентов и возвращает другой компонент.

Разбираемся со связкой React и Redux на простейшем примере

Простой пример, который поможет быстро разобраться, как управлять данными с помощью библиотеки Redux в ваших приложениях на React.

Комментарии (0)

Зарегистрируйтесь или авторизуйтесь, чтобы оставлять комментарии.