Главная » Статьи » Как работает setState React

Как работает setState React

Как работает setState React

От автора: React быстр! Частично это достигается за счет обновления только тех частей DOM, которые в этом нуждаются. Меньше того, о чем вам нужно беспокоиться, и больше скорости. Пока вы понимаете, что работает React setState (), вы можете продолжать. Тем не менее, важно также знать то, как эта удивительная библиотека обновляет DOM вашего приложения. Это знание будет играть важную роль в вашей работе в качестве разработчика React.

DOM?

Браузер создает DOM, анализируя код, который вы пишете, он делает это до того, как отобразит страницу. DOM представляет документы на странице в виде узлов и объектов, обеспечивая интерфейс, чтобы языки программирования могли подключаться к DOM и манипулировать им. Проблема с DOM заключается в том, что он не оптимизирована для приложений динамического интерфейса. Таким образом, обновление DOM может замедлить ваше приложение, когда есть много вещей, которые нужно изменить; поскольку браузер должен повторно применять все стили и отображать новые HTML-элементы. Это также происходит в ситуациях, когда ничего не меняется.

Что такое согласование?

Согласование — это процесс, посредством которого React обновляет DOM. Когда изменяется состояние компонента, React должен вычислить, необходимо ли обновлять DOM. Он делает это, создавая виртуальный DOM и сравнивая ее с текущим. В этом контексте виртуальный DOM будет содержать новое состояние компонента.

Давайте расстроим простой компонент, который добавит два числа. Числа будут введены в поле ввода.

Сначала нам нужно настроить начальное состояние для полей, а затем обновить состояние при вводе числа. Компонент будет выглядеть так:

class App extends React.Component { state = { result: '', entry1: '', entry2: '' } handleEntry1 = (event) => { this.setState({entry1: event.target.value}) } handleEntry2 = (event) => { this.setState({entry2: event.target.value}) } handleAddition = (event) => { const firstInt = parseInt(this.state.entry1) const secondInt = parseInt(this.state.entry2) this.setState({result: firstInt + secondInt }) } render() { const { entry1, entry2, result } = this.state return( <div> <div> <p>Entry 1: { entry1 }</p> <p>Entry 2: { entry2 }</p> <p>Result: { result }</p> </div> <br /> <div> Entry 1: <input type='text' onChange={this.handleEntry1} /> </div> <br /> <div> Entry 2: <input type='text' onChange={this.handleEntry2} /> </div> <div> <button onClick={this.handleAddition} type='submit'>Add</button> </div> </div> ) }
}

При первоначальном рендеринге дерево DOM будет выглядеть так:

Как работает setState React

Когда производится запись в первое поле ввода, React создает новое дерево. Новое дерево, являющееся виртуальным DOM, будет содержать новое состояние для entry1. Затем React сравнивает виртуальный DOM со старым, и вычисляет разницу между обеими DOM, после чего выполняет обновление только той части, которая отличается. Новое дерево создается каждый раз, когда изменяется состояние компонента приложения — когда значение вводится в любом из полей ввода или при нажатии кнопки.

Как работает setState React

Определение различий элементов

Когда состояние компонента изменяется так, что элемент необходимо изменить из одного типа в другой, React отключает все дерево и создает новое с нуля. Это приводит к уничтожению каждого узла в этом дереве. Давайте рассмотрим пример:

class App extends React.Component { state = { change: true } handleChange = (event) => { this.setState({change: !this.state.change}) } render() { const { change } = this.state return( <div> <div> <button onClick={this.handleChange}>Change</button> </div> { change ? <div> This is div cause it's true <h2>This is a h2 element in the div</h2> </div> : <p> This is a p element cause it's false <br /> This is another paragraph in the false paragraph </p> } </div> ) }
}

При первоначальном рендере вы увидите div и его содержимое, а также нажатие кнопки вызывает React для удаления дерева div с его содержимым и построения вместо этого дерева для элемента <p>. То же самое происходит, если в обоих случаях мы имеем один и тот же компонент. Компонент будет удален вместе с предыдущим деревом, к которому он принадлежал, и будет создан новый экземпляр. См. демо-версию ниже.

Список различий

React использует ключи для отслеживания элементов в списке. Ключи помогают определить позицию элемента в списке. Что происходит, когда список не имеет ключей? React будет изменять каждый дочерний элемент списка, даже если новых изменений не будет.

Другими словами, React изменяет каждый элемент в списке, который не имеет ключей. Вот пример:

const firstArr = ['codepen', 'codesandbox']
const secondArr = ['github', 'codepen', 'bitbucket', 'codesanbox'] class App extends React.Component { state = { change: true } handleChange = (event) => { this.setState({change: !this.state.change}) } render() { const { change } = this.state return( <div> <div> <button onClick={this.handleChange}>Change</button> </div> <ul> { change ? firstArr.map((e) => <li>{e}</li>) : secondArr.map((e) => <li>{e}</li>) } </ul> </div> ) }
}

Здесь мы имеем два массива, которые отображаются в зависимости от состояния компонента. Реакт не располагает способом отслеживать элементы в списке, поэтому он обязан изменять весь список каждый раз, когда возникает необходимость повторного рендеринга. Это приводит к проблемам с производительностью.

В консоли вы увидите предупреждение, подобное этому:

Warning: Each child in an array or iterator should have a unique "key" prop.

Чтобы исправить это, вы добавляете уникальный ключ для каждого элемента в списке.

const firstArr = ['codepen', 'codesandbox']
const secondArr = ['github', 'codepen', 'bitbucket', 'codesanbox'] class App extends React.Component { state = { change: true } handleChange = (event) => { this.setState({change: !this.state.change}) } render() { const { change } = this.state return( <div> <div> <button onClick={this.handleChange}>Change</button> </div> <ul> { change ? firstArr.map((e, index) => <li key={e.index}>{e}</li>) : secondArr.map((e, index) => <li key={e.index}>{e}</li>) } </ul> </div> ) }
}

Заключение

Итак, вот два основных преимущества которые дает применение концепции согласования в React:

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

React не выполняет полную перестройку узлов DOM. Он только изменяет то, что нужно. Данный процесс настолько быстр, что вы его можете даже не заметить.

Автор: Kingsley Silas

Источник: https://css-tricks.com/

Редакция: Команда webformyself.