Facebook React: Invariant Violation и элементы, которые не были автоматически установлены
Я изучаю Facebook React, делая небольшой пример.
Я решил проверить, были ли мои знания о привязке this
в порядке, поэтому я создал три React.class
, где изменяемые состояния находятся в родительском, а посередине только передают обратные вызовы детям, чтобы манипулировать им.
Основная структура:
- MainFrame (states here)
- FriendBox (only pass the callbacks for change states to Friend)
-Friend
Заметьте, что я мог бы использовать transferThisProp
, но на самом деле я предпочел сделать это "вручную".
Вывод FriendBox содержит следующее:
var allFriends = this.props.friends.map((function (f) {
return(
<Friend key = {f.id}
name = {f.name}
select = {this.props.select}
/>
)
}).bind(this))
Друг-рендер содержит следующее:
return(
<div className="friend">
{this.props.name}
<a href="" onClick={this.props.select(this.props.key)}>
select
</a>
</div>
)
При запуске моего кода я получаю следующее сообщение:
MainFrame.sendToFriendH:
Invariant Violation: receiveComponent(...):
Can only update a mounted component. react.js:7276
Uncaught Error: Invariant Violation:
receiveComponent(...): Can only update a mounted component.
Интересная часть заключается в том, что при использовании активного расширения для chrome я могу проверить, что виртуальный DOM
хорошо, и привязки в порядке. Все выглядит отлично, за исключением того, что компонент Child для первого элемента Friend
говорит _lifeCycleState: "UNMOUNTED"
Это заставило меня задуматься, чем я ошибаюсь, когда нижний ребенок не отображается и не монтируется.
Весь код выходит из строя, но я точно не знаю почему.
Может ли кто-нибудь сказать мне, почему элемент не устанавливается автоматически и как его исправить?
Полный код: http://jsfiddle.net/RvjeQ/
Ответы
Ответ 1
Когда вы пишете
onClick={this.props.select(this.props.key)}
вы вызываете обработчик this.props.select
немедленно и устанавливаете его результат как обработчик onClick. Я предполагаю, что вы хотите вместо этого сделать частичное приложение, которое вы можете использовать с помощью функции стрелки:
onClick={(e) => this.props.select.bind(this.props.key, e)}
Если вы не заботитесь о событии arg, вы можете пропустить его.
Вы также можете использовать .bind()
так:
onClick={this.props.select.bind(null, this.props.key)}
Ответ 2
Для чего это стоит, вам не нужно делать
this.props.friends.map((function(){ ... }).bind(this));
Второй аргумент Array.prototype.map позволяет установить контекст для функции обратного вызова. Используйте это вместо
this.props.friends.map(function(f){ ... }, this);
Вы также можете использовать Функция стрелки, которая имеет лексическую область
this.props.friends.map(f =>
<Friend key = {f.id}
name = {f.name}
select = {this.props.select}
/>
)
Кроме того, когда вы работаете со сложными реквизитами, вы можете делать такие вещи, как
var props = {
key: f.id,
name: f.name,
select: this.props.select
};
<Friend {...props} />