JSX реквизиты не должны использовать.bind() - как избежать использования bind?
У меня есть контейнер, который мне нужен, чтобы изменить форму пользовательского интерфейса, показывая форму или страницу успеха.
Контейнер имеет state.showSuccess, и мне нужно, чтобы MyFormModule мог вызывать контейнер для изменения состояния.
Приведенный ниже код работает, но я получаю следующее предупреждение:
"JSX реквизиты не должны использовать.bind()"
Как я могу заставить это работать без использования.bind()?
...
const myPage = class extends React.Component {
state = { showSuccess: false };
showSuccess() {
this.setState({
showSuccess: true,
});
}
render() {
const { showSuccess } = this.state;
if (showSuccess) {...}
....
<MyFormModule showSuccess={this.showSuccess.bind(this)} />
3 ответа
Сначала вы должны понять, ПОЧЕМУ это плохая практика.
Основная причина здесь в том, что .bind
возвращает ссылку на новую функцию.
Это будет происходить на каждом render
вызов, который может привести к падению производительности.
У вас есть 2 варианта:
Используйте конструктор для
bind
ваши обработчики (это будет выполняться только один раз).constructor(props) { super(props); this.showSuccess = this.showSuccess.bind(this); }
Или создайте ваши обработчики с помощью функций стрелок, чтобы они использовали лексический контекст для
this
следовательно, вам не нужноbind
их вообще ( вам понадобится плагин babel):showSuccess = () => { this.setState({ showSuccess: true, }); }
Вы не должны использовать этот шаблон (как предлагали другие):
showSuccess={() => this.showSuccess()}
Потому что это также создаст новую функцию для каждого рендера.
Таким образом, вы можете обойти предупреждение, но вы все еще пишете свой код с плохой практикой.
Функция связывания или стрелка в опоре JSX создаст совершенно новую функцию для каждого рендера. Это отрицательно сказывается на производительности, так как приводит к тому, что сборщик мусора будет вызываться больше, чем необходимо. Это также может привести к ненужным повторным визуализациям, если совершенно новая функция передается в качестве реквизита компоненту, который использует проверку равенства ссылок на реквизит для определения необходимости обновления.
Используйте функцию стрелки при определении showSuccess
showSuccess = () => {
this.setState({
showSuccess: true,
});
}
Используйте функцию стрелки, так как они автоматически наследуют this
контекст, где они определены.
showSuccess={() => this.showSuccess()}
Вот ссылка на документацию Facebook на эту тему, в которой этот метод указан как решение. Интересно, что они также перечисляют использование .bind
в опоре в качестве одного из решений, хотя оно и выдает предупреждение при фактическом использовании.
Из этой документации вы заметите, что это потенциальная проблема с производительностью, так как функция будет воссоздана при каждом рендере:
Замечания:
Использование функции стрелки в рендере создает новую функцию каждый раз при рендеринге компонента, что может влиять на производительность (см. Ниже).
Но также по той же ссылке:
Можно ли использовать функции стрелок в методах рендеринга? В общем, да, это нормально, и часто это самый простой способ передать параметры в функции обратного вызова.
Если у вас есть проблемы с производительностью, обязательно оптимизируйте!
Поэтому я бы сказал, что если ваш компонент будет выполнять рендеринг очень часто, вам следует использовать одно из других решений: связать в конструкторе или сначала определить метод с помощью функции стрелки. Но если нет, используйте любой метод, который кажется вам наиболее чистым.