Ответ 1
Я разговаривал с несколькими людьми на канале Discord #reactiflux и фактически получил ответ, который искал.
В основном, есть три варианта использования с компонентами React, и в некоторых из них параметры деструктурирования влияют на производительность, поэтому важно понимать, что происходит на самом деле.
Функциональный компонент без сохранения состояния
const MyComponent = ({ name = 'John Doe', displayName = humanize(name), address = helper.getDefaultAddress() }) => {
return (
<div>{displayName}</div>
);
};
Это функциональный компонент без сохранения состояния. Нет состояния, и оно функционально, потому что это не экземпляр Class
, а простая функция.
В этом случае жизненного цикла нет, у вас не может быть componentWillMount
или shouldComponentUpdate
или constructor
. И поскольку отсутствует управление жизненным циклом, оно никак не влияет на производительность. Этот код совершенно действителен. Некоторые могут предпочесть обработать значение по умолчанию displayName
в теле функции, но, в конце концов, это не имеет значения, это не повлияет на производительность.
Нефункциональный компонент без состояния
(Не делай этого!)
class MyComponent extends React.Component {
render() {
const { name = 'John Doe', displayName = humanize(name), address = helper.getDefaultAddress() } = this.props;
return (
<div>{displayName}</div>
);
}
}
Это нефункциональный компонент без сохранения состояния. Нет состояния, но оно не "функционально", так как это class
. И поскольку это класс, расширяющий React.Component
, это означает, что у вас будет жизненный цикл. Вы можете иметь componentWillMount
или shouldComponentUpdate
или constructor
там.
А поскольку он имеет жизненный цикл, способ написания этого компонента плох. Но почему?
Проще говоря, React предлагает атрибут defaultProps
для работы со значениями реквизита по умолчанию. И на самом деле лучше использовать его при работе с нефункциональными компонентами, потому что он будет вызываться всеми методами, основанными на this.props
.
В предыдущем фрагменте кода создаются новые локальные переменные с именами name
и displayName
, но значения по умолчанию применяются только для этого метода render
!. Если вы хотите, чтобы значения по умолчанию применялись для каждого метода, например значений из жизненного цикла React (shouldComponentUpdate
и т.д.), Тогда вы должны использовать вместо него defaultProps
.
Таким образом, предыдущий код на самом деле является ошибкой, которая может привести к неправильному пониманию значения по умолчанию name
.
Вот как это должно быть написано, чтобы получить то же поведение:
class MyComponent extends React.Component {
render() {
const { name, displayName = humanize(name), address } = this.props;
return (
<div>{displayName}</div>
);
}
}
MyComponent.defaultProps = {
name: 'John Doe',
address: helper.getDefaultAddress(),
};
Это лучше. Потому что имя всегда будет John Doe
, если оно не было определено. address
Значение по умолчанию также рассматривалось, но не displayName
... Почему?
Ну, я еще не нашел способ обойти этот особый вариант использования. Потому что displayName
должен основываться на свойстве name
, к которому мы не можем получить доступ (AFAIK) при определении defaultProps
. Единственный способ, которым я вижу, - иметь дело с этим напрямую в методе render
. Может быть, есть лучший способ.
У нас нет этой проблемы со свойством address
, поскольку оно не основано на свойствах MyComponent, а полагается на что-то совершенно независимое, которое не нуждается в подпорках.
Нефункциональный компонент с состоянием
Он работает точно так же, как "Нефункциональный компонент без состояния". Поскольку жизненный цикл еще существует, поведение будет таким же. Тот факт, что в компоненте есть дополнительный внутренний state
, ничего не изменит.
Я надеюсь, что это помогает понять при использовании деструктуризации с компонентами. Мне очень нравится функциональный способ, он намного чище ИМХО (+1 для простоты).
Вы можете предпочесть всегда использовать defaultProps
, независимо от того, работаете ли вы с функциональными или нефункциональными компонентами, это также допустимо. (+1 для согласованности)
Просто помните о жизненном цикле с нефункциональными компонентами, которые "требуют" использования defaultProps
. Но в конце концов выбор всегда остается за вами;)
Изменить 10-2019: defaultProps в конечном итоге будет удалено из React API в будущем, см. fooobar.com/questions/2444550/... и https://github.com/reactjs/rfcs/pull/107 для RFC.