Мой код работает, но у меня есть вопрос с наилучшей практикой: у меня есть массив объектов в состоянии, и взаимодействие с пользователем изменяет значение одного объекта за раз. Насколько я знаю, я не должен напрямую менять состояние, я всегда должен использовать setState
. Если я хочу избежать этого с любой ценой, я буду глубоко клонировать массив по итерации и изменять клон. Затем установите состояние в клон. По-моему, избежать изменения состояния, которое я буду менять позже, просто снижает мою производительность.React - Изменение состояния без использования setState: нужно избегать этого?
Подробной версия: this.state.data представляет собой массив объектов. Он представляет список тем на форуме, а кнопка «Избранное» переключается, вызывая clickCollect()
. Поскольку у меня есть массив в состоянии, когда я изменяю свойство is_collected одного элемента, мне нужно создать копию массива для работы, и после изменения на новое значение я могу установить его в состояние.
var data = this.state.data.slice(0); data[index].is_collected = !data[index].is_collected; this.setState({data: data});
var data = this.state.data
: Это скопирует указатель на массив и толчке(), сдвиг(), и т.д. изменяет состояние непосредственно. Будут затронуты как data
, так и this.state.data
.
var data = this.state.data.slice(0)
: Это делает мелкий клон, нажатие и сдвиг не изменяет состояние, но в моем клоне у меня все еще есть указатели на элементы массива состояния. Поэтому, если я изменю data[0].is_collected
, также будет изменен this.state.data[0].is_collected
. Это происходит до того, как я позвоню setState()
.
Обычно я должен сделать:
var data = []; for (var i in this.state.data) { data.push(this.state.data[i]); }
Затем изменить значение по индексу, установив его истинным, когда оно ложно или ложным, когда это правда:
data[index].is_collected = !data[index].is_collected;
И изменение состояния:
this.setState({data: data});
Рассмотрим мой массив является относительно большим или чрезвычайно большим, я думаю, эта итерация уменьшит производительность моего APP. Я заплатил бы эту стоимость, если бы знал, что это правильный путь по любой причине. Однако в этой функции (clickCollect
) я всегда устанавливаю новое значение в состояние, я не жду ложного ответа API, который бы сказал, чтобы прекратить внесение изменений. Во всех случаях новое значение переходит в состояние. Практически я звоню setState
только для того, чтобы пользовательский интерфейс снова отображался. Так что вопросы:
- Должен ли я создать глубокий клон в этом случае? (
for var i in ...
) - Если нет, имеет смысл сделать мелкий клон (
.slice(0)
), если в моем массиве содержатся объекты? Изменения происходят над объектами внутри массива, поэтому мелкий клон все еще меняет свое состояние, как и копия (data = this.state.data
).
Мой код упрощен, а вызовы API вырезаны для простоты.
Это вопрос новичка, поэтому также возможен и совершенно другой подход. Или ссылки на другие Q & A.
import React from 'react'; var ForumList = React.createClass({ render: function() { return <div className="section-inner"> {this.state.data.map(this.eachBox)} </div> }, eachBox: function(box, i) { return <div key={i} className="box-door"> <div className={"favorite " + (box.is_collected ? "on" : "off")} onTouchStart={this.clickCollect.bind(null, i)}> {box.id} </div> </div> }, getInitialState: function() { return {data: [ { id: 47, is_collected: false }, { id: 23, is_collected: false }, { id: 5, is_collected: true } ]}; }, clickCollect: function(index) { var data = this.state.data.slice(0); data[index].is_collected = !data[index].is_collected; this.setState({data: data}); } }); module.exports = ForumList;
Спасибо всем за ваши ответы. Я не могу на самом деле «принять» одну из них, поскольку все четыре поставили некоторые проблемы с проблемой с разных точек зрения. Тем не менее, @CodinCat получает согласие, чтобы четко сформулировать свой ответ.Особая благодарность VJAI, Kelvin De Moya и Degr. –