Как использовать метод lifecycle getDerivedStateFromProps, а не componentWillReceiveProps
Похоже, что в следующих выпусках componentWillReceiveProps
будет полностью прекращен в пользу нового метода жизненного цикла getDerivedStateFromProps
:static getDerivedStateFromProps().
После проверки кажется, что вы теперь не можете провести прямое сравнение между this.props
и nextProps
, как вы можете это сделать в componentWillReceiveProps
. Есть ли способ обойти это?
Кроме того, теперь он возвращает объект. Правильно ли я предположить, что возвращаемое значение по существу this.setState
?
Ниже приведен пример, который я нашел в Интернете: Состояние, полученное из реквизита/состояния.
Перед
class ExampleComponent extends React.Component {
state = {
derivedData: computeDerivedState(this.props)
};
componentWillReceiveProps(nextProps) {
if (this.props.someValue !== nextProps.someValue) {
this.setState({
derivedData: computeDerivedState(nextProps)
});
}
}
}
После того, как
After
class ExampleComponent extends React.Component {
// Initialize state in constructor,
// Or with a property initializer.
state = {};
static getDerivedStateFromProps(nextProps, prevState) {
if (prevState.someMirroredValue !== nextProps.someValue) {
return {
derivedData: computeDerivedState(nextProps),
someMirroredValue: nextProps.someValue
};
}
// Return null to indicate no change to state.
return null;
}
}
Ответы
Ответ 1
Об удалении componentWillReceiveProps
: вы должны иметь возможность обрабатывать его использование с помощью комбинации getDerivedStateFromProps
и componentDidUpdate
, см. сообщение в блоге React, например, о миграциях. И да, объект, возвращаемый getDerivedStateFromProps
, обновляет состояние аналогично объекту, переданному в setState
.
Если вам действительно нужно старое значение реквизита, вы всегда можете кэшировать его в своем состоянии примерно так:
state = {
cachedSomeProp: null
// ... rest of initial state
};
static getDerivedStateFromProps(nextProps, prevState) {
// do things with nextProps.someProp and prevState.cachedSomeProp
return {
cachedSomeProp: nextProps.someProp,
// ... other derived state properties
};
}
Все, что не влияет на состояние, можно поместить в componentDidUpdate
, а там даже getSnapshotBeforeUpdate
для вещей очень низкого уровня.
ОБНОВЛЕНИЕ: чтобы узнать о новых (и старых) методах жизненного цикла, может быть полезен пакет реагировать-жизненный цикл-визуализатор.
Ответ 2
Как мы недавно опубликовали в блоге React , в подавляющем большинстве случаев вам вообще не нужны getDerivedStateFromProps
.
Если вы просто хотите вычислить некоторые производные данные, либо:
- Сделайте это прямо внутри
render
- Или, если пересчитать это дорого, используйте помощник
memoize-one
например memoize-one
.
Вот простейший пример "после":
import memoize from "memoize-one";
class ExampleComponent extends React.Component {
getDerivedData = memoize(computeDerivedState);
render() {
const derivedData = this.getDerivedData(this.props.someValue);
// ...
}
}
Просмотрите этот раздел в блоге, чтобы узнать больше.
Ответ 3
Как упоминал Дэн Абрамов
Сделайте это прямо внутри рендера
Мы на самом деле используем этот подход с memoise one для любых прокси-серверов, чтобы подсчитывать вычисления.
Наш код выглядит так
// ./decorators/memoized.js
import memoizeOne from 'memoize-one';
export function memoized(target, key, descriptor) {
descriptor.value = memoizeOne(descriptor.value);
return descriptor;
}
// ./components/exampleComponent.js
import React from 'react';
import { memoized } from 'src/decorators';
class ExampleComponent extends React.Component {
buildValuesFromProps() {
const {
watchedProp1,
watchedProp2,
watchedProp3,
watchedProp4,
watchedProp5,
} = this.props
return {
value1: buildValue1(watchedProp1, watchedProp2),
value2: buildValue2(watchedProp1, watchedProp3, watchedProp5),
value3: buildValue3(watchedProp3, watchedProp4, watchedProp5),
}
}
@memoized
buildValue1(watchedProp1, watchedProp2) {
return ...;
}
@memoized
buildValue2(watchedProp1, watchedProp3, watchedProp5) {
return ...;
}
@memoized
buildValue3(watchedProp3, watchedProp4, watchedProp5) {
return ...;
}
render() {
const {
value1,
value2,
value3
} = this.buildValuesFromProps();
return (
<div>
<Component1 value={value1}>
<Component2 value={value2}>
<Component3 value={value3}>
</div>
);
}
}
Преимущества этого в том, что вам не нужно кодировать тонны шаблона сравнения внутри getDerivedStateFromProps
или componentWillReceiveProps
и вы можете пропустить инициализацию копий-пасты внутри конструктора.
ЗАМЕТКА:
Этот подход используется только для проксирования реквизита, чтобы заявить, в случае, если у вас есть внутренняя логика состояния, все равно его нужно обрабатывать в жизненных циклах компонентов.