Я понимаю ваш вопрос как "почему, когда я помещаю новый элемент в самом начале массива, кажется, что новый компонент React создан для самого последнего элемента?"
Причина в том, что key
используется для index
.
Исходя из его логики (отметьте Lists and Keys раздел в документации), поскольку только последний элемент (с новым индексом oldLength + 1
) имеет уникальный key
, только он будет создан с нуля. Пока все остальные просто перерисованы и обновлены. Другими словами, ваш код обновляет элементы N - 1
вместо того, чтобы просто создавать 1 новый и оставлять все остальные без изменений.
Чтобы справиться с этим, вы не должны полагаться на index
в key
, но должны использовать другое предсказуемое, стабильное и незанятое значение. В вашем случае это prop1
. Тогда конструктор будет вызван для самого первого элемента.
Вот обновленная версия
class ComponentB extends Component {
constructor(props) {
super(props) // added upon first reply
this.state = {
objects: []
};
}
handleObjectAdd = () => {
this.setState(oldState => ({
objects: [
{prop1: this.state.objects.length + 1},
...oldState.objects
]
}))
}
render() {
return (
<div>
<button onClick={this.handleObjectAdd}>ADD</button>
{this.state.objects.map(obj =>
<ComponentA key={obj.prop1} details={obj} />
)}
</div>
)
}
}
class ComponentA extends Component {
constructor(props) {
super(props) // added upon first reply
console.log('ComponentA constructor called');
}
render() {
console.log('ComponentA render() called');
return (
<input type="text" value={this.props.details.prop1}></input>
)
}
}
Ваш исходный код имеет несколько синтаксических ошибок и измененное состояние напрямую (никогда не делают этого), поэтому он никогда не рендерится после нажатия кнопки. Пожалуйста, проверяйте код в следующий раз, когда вы отправите вопрос - это облегчит понимание / ответ.
[UPD] извлек часть фрагмента из комментариев ниже
вместо того, чтобы просто создать 1 новое и оставить все остальное без изменений.
React не пытается минимизировать количество операций. При сравнении [1,2,3] и [0, 1, 2, 3] есть 2 возможных способа: либо «вставить 0 в начале, сдвигая все остальное», либо «уменьшить все элементы на 1 и дополнительно вставить 3 в конец'. Если вы предоставляете хорошую недвижимость в качестве ключа, React подбирает 1-е решение. Но имея key = {index}, вы буквально говорите: «Реагируйте, используйте 2-й подход, я знаю, что делаю». React не анализирует код, который вы запускаете перед вызовом .setState, он просто полагается на значение ключа.