Эта статья является одной из серии статей на тему «подкова · React», и в будущем будет запущено больше тем.
иди ко мнеGitHub repoПрочитайте полную тему статья
иди ко мнеличный блогПолучите непревзойденный опыт чтения
Жизненный цикл, как следует из названия, представляет собой процесс от рождения до смерти.
Крюк жизненного цикла — ключевой узел в процессе от рождения до смерти.
Какие зацепки жизненного цикла есть в жизни обычного человека?
- Родился
- принят в университет
- Первая работа
- купить дом
- выходит замуж
- рожать
- Крючки дочернего жизненного цикла
- выходить на пенсию
- Последние слова
В каждый критический момент нам всегда хочется немного поразмышлять, потому что решения, которые мы принимаем в это время, изменят направление нашей жизни.
То же самое касается компонентов React, которые дадут разработчикам несколько моментов для размышлений, когда они могут изменить направление компонента.
Жизненный цикл при асинхронном рендеринге
React потребовалось два года, чтобы придумать механизм рендеринга Fiber.
Проще говоря, React называет процесс сравнения согласованием. Раньше этот процесс выполнялся за один раз, но механизм Fiber изменил его на асинхронный. Асинхронные навыки будут постепенно разблокированы в следующей версии.
Очевидно, что это синхронный код, почему он асинхронный?
Принцип заключается в том, что Файбер делит задачу на мелкие части, и возвращает управление основному потоку каждый раз, когда часть выполняется, а затем выполняет оставшиеся задачи после того, как основной поток занят текущей работой. Конечно, если время выполнения какого-то куска очень велико (например, бесконечный цикл), то основной поток тут ни при чем, и пора крашиться.
Как это влияет на жизненный цикл?
В результате жизненный цикл перед монтированием и обновлением становится ненадежным.
Почему ты это сказал? Поскольку процесс согласования может быть приостановлен, а затем продолжать выполняться, обработчик жизненного цикла перед монтированием и обновлением может не выполняться или выполняться несколько раз, а его производительность непредсказуема.
Таким образом, жизненный цикл React после 16 лет принес волну изменений, и постепенно будут отказываться от следующих зацепок жизненного цикла:
- componentWillMount
- componentWillReceiveProps
- componentWillUpdate
Вы видите характеристики, они все имеютwill
крюк.
React в настоящее время предоставляет псевдонимы для этих хуков жизненного цикла, а именно:
- UNSAFE_componentWillMount
- UNSAFE_componentWillReceiveProps
- UNSAFE_componentWillUpdate
React17 будет предоставлять только псевдонимы, полностью отказываясь от этих трех больших живых сокровищ. Принять такой псевдоним означает сделать вас больным.
constructor()
React заимствует классconstructor
Действует как хук инициализации.
React почти ничего не делает, но поскольку мы разрешаем передавать параметры компонентам только по определенным путям, поэтомуconstructor
Параметры фактически определяются React.
Реагировать оговариваетconstructor
Есть три параметра, которыеprops
,context
а такжеupdater
.
-
props
является свойством, оно неизменно. -
context
является глобальным контекстом. -
updater
это объект, содержащий некоторые методы обновления,this.setState
Последний звонокthis.updater.enqueueSetState
метод,this.forceUpdate
Последний звонокthis.updater.enqueueForceUpdate
метод, поэтому эти API больше используются внутри React и доступны для нужд разработчиков.
В React, поскольку все компоненты класса наследуются отComponent
класс илиPureComponent
класс, так же, как метод написания собственного класса, его нужно написать вconstructor
сначала позвониsuper
метод полученияthis
.
constructor
Лучшей практикой для хуков жизненного цикла является инициализация здесьthis.state
.
Конечно, вместо этого вы также можете использовать инициализаторы свойств, как показано ниже:
import React, { Component } from 'react';
class App extends Component {
state = {
name: 'biu',
};
}
export default App;
componentWillMount()
💀 Это API устарело в React.
Это хук жизненного цикла до того, как компонент будет смонтирован в DOM.
У многих возникает непонимание: этот хук — лучшее время для запроса данных, а затем вставки данных в элемент и их монтирования вместе.
фактическиcomponentWillMount
Причем крепление выполняется синхронно, а это значит, что после выполнения хука он монтируется сразу. Запрос данных с сервера выполняется асинхронно. Таким образом, каким бы быстрым ни был запрос, он должен быть обработан после задачи синхронизации, что является проблемой генерации.
То есть здесь никогда нельзя вставлять данные в элементы и монтировать их вместе.
Дело не в том, что здесь нельзя запросить данные, а в том, что вы не можете добиться того эффекта, который себе представляете.
Он устарел по двум основным причинам:
- Это было бесполезно изначально. Предполагается, что он был создан с целью спаривания.
- Если он объявляет таймер или подписчика при рендеринге на стороне сервера,
componentWillUnmount
Код очистки в хуках жизненного цикла не вступит в силу. Потому что, если компонент не смонтирован успешно,componentWillUnmount
выполняться не будет. Яо Мин сказал: «Если нет верховой езды, то нет и разъединения». - При асинхронном рендеринге он ведет себя хаотично.
инициализацияthis.state
должен быть вconstructor
Завершено в хуке жизненного цикла, данные запроса должны быть вcomponentDidMount
Крючок жизненного цикла завершен, поэтому он не только заброшен, но и преемники.
static getDerivedStateFromProps(props, state)
👽 Это API, выпущенный React v16.3.0.
Во-первых, это хук жизненного цикла статического метода.
То есть при определении вы должны добавить метод перед методом.static
ключевое слово или напрямую смонтировать его в классе class.
Кратко различайте методы экземпляра и статические методы:
- метод экземпляра, смонтированный в
this
на или установлен наprototype
Выше класс класса не может напрямую обращаться к этому методу, используйтеnew
После создания экземпляра ключевого слова экземпляр может получить доступ к методу. - Статические методы, монтируемые непосредственно в класс класса или использующие новые ключевые слова
static
, экземпляр не может получить доступ к методу напрямую.
Вопрос в том, почемуgetDerivedStateFromProps
Должны ли хуки жизненного цикла разрабатываться как статические методы?
Таким образом, разработчики не могут получить доступthis
То есть это экземпляр, и в нем нельзя вызывать методы экземпляра или setState.
import React, { Component } from 'react';
class App extends Component {
render() {
return (
<div>React</div>
);
}
static getDerivedStateFromProps(props, state) {}
}
export default App;
Миссия этого хука жизненного цикла состоит в том, чтобы обновлять свое собственное состояние по запросу на основе свойств родительского компонента.Это состояние называется производным состоянием. Возвращаемый объект — это состояние, которое будет постепенно обновляться.
Он разработан как статический метод, чтобы сохранить чистоту метода, он используется для определения производного состояния и не должен выполнять в нем никаких операций.
Этот крючок жизненного цикла также претерпел некоторые повороты, он изначально был разработан, чтобы初始化
,父组件更新
а также接收到props
будет запущен, и теперь он будет запускаться до тех пор, пока выполняется рендеринг, то есть初始化
а также更新阶段
сработает.
render()
Основной функцией компонента является монтирование элементов в DOM, поэтомуrender
Крючки жизненного цикла обязательно будут использоваться.
render
Как хуки жизненного цикла получают шаблоны? Конечно, вы вернетесь к нему.
Однако не рекомендуется писать слишком много логики перед возвратом, если логики слишком много, ее можно инкапсулировать в функцию.
render() {
// 这里可以写一些逻辑
return (
<div>
<input type="text" />
<button>click</button>
</div>
);
}
Будьте осторожны, неrender
Вызывается в хуках жизненного циклаthis.setState
,потому чтоthis.setState
Это вызовет рендер, и он никогда не закончится. Господи, есть предатель.
componentDidMount()
Это хук жизненного цикла после того, как компонент смонтирован в DOM.
Это может быть в дополнение кrender
Самый важный крючок жизненного цикла за пределами , потому что все аспекты компонента уже готовы, и мир зависит от вас.
Это социальный брат, здесь не так много жестоких слов.
componentWillReceiveProps(nextProps)
💀 Это API устарело в React.
componentWillReceiveProps
Хук жизненного цикла имеет только один параметр — update props.
Функция периода объявления может быть активирована в двух случаях:
- Компонент получил новые свойства.
- Компонент не получил новых свойств, но текущий компонент также был перерендерен из-за перерендеринга родителя.
Этот хук жизненного цикла не запускается во время инициализации.
Опять же, этот хук жизненного цикла может срабатывать несколько раз из-за введения механизма Fiber.
shouldComponentUpdate(nextProps, nextState)
Эта ловушка жизненного цикла представляет собой переключатель, который определяет, требуется ли обновление, и в основном используется для оптимизации производительности.
Существует исключение, если разработчик вызываетthis.forceUpdate
Принудительное обновление, компоненты React будут игнорировать этот хук.
shouldComponentUpdate
Крючки жизненного цикла по умолчанию возвращают true. То есть по умолчанию компонент всегда будет обновляться всякий раз, когда компонент инициирует обновление. React дает разработчику контроль над суждениями.
Но продуманный React также предоставляетPureComponent
базовый класс, аналогичныйComponent
Разница между базовыми классамиPureComponent
автоматически реализуетshouldComponentUpdate
Крючки жизненного цикла.
Для компонентов повторный рендеринг требуется только в случае изменения состояния. такshouldComponentUpdate
Крючки жизненного цикла предоставляют два параметра, которые разработчики могут сравниватьthis.props
а такжеnextProps
,this.state
а такжеnextState
Чтобы определить, изменилось ли состояние, а затем вернуть значение true или false соответственно.
При каких обстоятельствах состояние не меняется, но все же запускает обновление? Например:
Родительский компонент передает значение дочернему компоненту.При изменении состояния родительского компонента, даже если значение, полученное дочерним компонентом, не меняется, дочерний компонент будет принудительно обновлен. Это явно очень неразумно, React ничего не может с этим поделать, он может только смотреть на личное творение разработчика.
import React, { Component } from 'react';
import Child from './Child';
class App extends Component {
state = { name: 'React', star: 1 };
render() {
const { name, star } = this.state;
return (
<div>
<Child name={name} />
<div>{star}</div>
<button onClick={this.handle}>click</button>
</div>
);
}
handle = () => {
this.setState(prevState => ({ star: ++prevState.star }));
}
}
export default App;
import React, { Component } from 'react';
class Child extends Component {
render() {
return <h1>{this.props.name}</h1>;
}
shouldComponentUpdate(nextProps, nextState) {
if (this.props === nextProps) {
return false;
} else {
return true;
}
}
}
export default Child;
Также обратите внимание на ямы эталонных типов.
В следующем случаеthis.props
а такжеnextProps
никогда не может быть равным.
import React, { Component } from 'react';
import Child from './Child';
class App extends Component {
state = { name: 'React', star: 1 };
render() {
return (
<div>
<Child name={{ friend: 'Vue' }} />
<div>{this.state.star}</div>
<button onClick={this.handle}>click</button>
</div>
);
}
handle = () => {
this.setState(prevState => ({ star: ++prevState.star }));
}
}
export default App;
import React, { Component } from 'react';
class Child extends Component {
render() {
return <h1>{this.props.friend}</h1>;
}
shouldComponentUpdate(nextProps, nextState) {
if (this.props === nextProps) {
return false;
} else {
return true;
}
}
}
export default Child;
Есть два обходных пути:
- Сравнивать
this.props.xxx
а такжеnextProps.xxx
. - Кэшировать ссылочный тип в переменной родительского компонента.
такthis.state
а такжеnextState
Его можно сравнить только с первым методом, потому что React будет возвращать новый объект каждый раз, когда обновляет состояние, вместо того, чтобы модифицировать исходный объект.
componentWillUpdate(nextProps, nextState)
💀 Это API устарело в React.
shouldComponentUpdate
Хук жизненного цикла возвращает true или вызываетthis.forceUpdate
После этого хук жизненного цикла выполняется немедленно.
Обратите особое внимание,componentWillUpdate
Хук жизненного цикла будет выполняться перед каждым обновлением, поэтому вызовите его здесь.this.setState
Это очень опасно и может быть бесконечным.
Кроме того, из-за введения механизма Fiber этот хук жизненного цикла может вызываться несколько раз.
getSnapshotBeforeUpdate(prevProps, prevState)
👽 Это API, выпущенный React v16.3.0.
Как следует из названия, он используется для сохранения моментальных снимков состояния.
Он будет вызван, когда компонент будет смонтирован, обратите внимание, что он вот-вот будет смонтирован. это даже звонит, чемrender
Слишком поздно, так что вы можете видетьrender
Операция монтирования не завершена, но выполнена работа по построению абстрактного пользовательского интерфейса.getSnapshotBeforeUpdate
Немедленное выполнение вызоваcomponentDidUpdate
Крючки жизненного цикла.
Для чего это? Есть некоторые состояния, такие как положение прокрутки веб-страницы, которые мне не нужно сохранять, мне просто нужно иметь возможность восстановить исходное положение после обновления компонента.
getSnapshotBeforeUpdate
Значение, возвращаемое хуком жизненного цикла, будетcomponentDidUpdate
Получен третий параметр, мы можем использовать этот канал для сохранения некоторых состояний, которые не нужно сохранять, и их можно отбросить, когда они израсходуются.
Очевидно, он используется для заменыcomponentWillUpdate
Крючки жизненного цикла.
То есть разработчики обычно его не используют.
componentDidUpdate(nextProps, nextState, snapshot)
Это хук жизненного цикла, который срабатывает после обновления компонента.
соответствоватьgetSnapshotBeforeUpdate
Когда используется хук жизненного цикла, третий параметрgetSnapshotBeforeUpdate
Возвращаемое значение.
такой же,componentDidUpdate
Хук жизненного цикла будет выполняться после каждого обновления, поэтому вызовите его здесь.this.setState
Это также очень опасно и может быть бесконечным.
componentWillUnmount()
Это хук жизненного цикла до размонтирования компонента.
Зачем нужен момент созерцания, когда компоненты вот-вот будут удалены?
Потому что разработчики хотят подтереть акридиновый зад.
Лучшая практика React заключается в том, что прослушиватели событий, подписчики и таймеры, используемые в компонентах, здесь уничтожаются.
Конечно, когда я говорю прослушиватели событий, я имею в виду следующее:
componentDidMount() {
document.addEventListener('click', () => {});
}
Поскольку следующий React будет автоматически уничтожен, не беспокойте разработчиков.
render(
return (
<button onClick={this.handle}>click</button>
);
)
componentDidCatch(error, info)
👽 Это API, выпущенный React v16.3.0.
Он в основном используется для обнаружения ошибок и соответствующей их обработки, поэтому его использование также является особенным.
пользовательский только одинcomponentDidCatch
крючки жизненного циклаErrorBoundary
компонента, он делает одно: если обнаружена ошибка, показывает сообщение об ошибке, если ошибок нет, показывает дочерний компонент.
Поместите компонент, который должен поймать ошибку, какErrorBoundary
Рендеринг дочернего компонента, как только дочерний компонент выдает ошибку, все приложение не падает, аErrorBoundary
захватывать.
import React, { Component } from 'react';
class ErrorBoundary extends Component {
state = { hasError: false };
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
componentDidCatch(error, info) {
this.setState({ hasError: true });
}
}
export default ErrorBoundary;
import React from 'react';
import ErrorBoundary from './ErrorBoundary';
import MyWidget from './MyWidget';
const App = () => {
return (
<ErrorBoundary>
<MyWidget />
</ErrorBoundary>
);
}
export default App;
Жизненный цикл
С таким количеством зацепок жизненного цикла на самом деле можно суммировать только три процесса:
- устанавливать
- возобновить
- удалить
Монтирование и размонтирование выполняются только один раз, а обновления выполняются несколько раз.
Полный жизненный цикл компонента React будет последовательно вызывать следующие хуки:
old lifecycle
-
устанавливать
- constructor
- componentWillMount
- render
- componentDidMount
-
возобновить
- componentWillReceiveProps
- shouldComponentUpdate
- componentWillUpdate
- render
- componentDidUpdate
-
удалить
- componentWillUnmount
new lifecycle
-
устанавливать
- constructor
- getDerivedStateFromProps
- render
- componentDidMount
-
возобновить
- getDerivedStateFromProps
- shouldComponentUpdate
- render
- getSnapshotBeforeUpdate
- componentDidUpdate
-
удалить
- componentWillUnmount
Стек вызовов жизненного цикла дерева компонентов
Когда приложение впервые монтируется, мы начинаем сrender
а такжеcomponentDidMount
Например, React сначала вызовет корневой компонентrender
Хуки, если есть подкомпоненты, вызывают подкомпоненты по очередиrender
Хук, вызывающий процесс на самом деле представляет собой рекурсивную последовательность.
и т.д. всех компонентовrender
Все хуки выполняются рекурсивно, в это время право на выполнение находится в руках последнего подкомпонента, поэтому запускается следующий раунд хуков жизненного цикла и вызывается последний подкомпонент.componentDidMount
ловушка, а затем стек вызовов рекурсивно вверх.
Стек вызовов жизненного цикла дерева компонентов имеет зигзагообразную форму.
Если корневой компонент не определяет обработчик жизненного цикла A, а подкомпонент определяет, то стек вызовов начинается с обработчика жизненного цикла A этого подкомпонента.
Кроме того, пока в компоненте определен определенный хук жизненного цикла, он будет выполняться, даже если он не выполняет никаких действий.
app.render();
child.render();
grandson.render();
// divide
grandson.componentDidMount();
child.componentDidMount();
app.componentDidMount();
// divide
app.render();
child.render();
grandson.render();
// divide
grandson.componentDidUpdate();
child.componentDidUpdate();
app.componentDidUpdate();
Конечно, хуки жизненного цикла componentWillMount, componentWillReceiveProps и componentWillUpdate могут прерываться или вызываться несколько раз, а производительность нестабильна. Поэтому React решил отказаться от них постепенно.
Однако понимание нормального порядка вызовов на протяжении жизненного цикла приложения полезно для понимания React.
Краткий обзор тем React