我的代码有效,但是我有一个最佳实践问题:状态中有一组对象,并且用户交互一次将更改一个对象的值。
据我所知,我不应该直接更改状态,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
:这会将指针复制到数组,而push(),shift()等将直接更改状态。双方data
并this.state.data
会受到影响。
var data = this.state.data.slice(0)
:这将形成一个浅表克隆,push和shift不会更改状态,但是在我的克隆中,我仍然具有指向状态数组元素的指针。因此,如果我更改了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]); }
然后,我更改index处的值,如果为false则将其设置为true,否则将其设置为false:
data[index].is_collected = !data[index].is_collected;
并更改状态:
this.setState({data: data});
考虑到我的数组比较大还是很大,我猜想这个迭代会降低我的APP的性能。如果我知道出于任何原因这是正确的方法,我将支付该费用。但是,在此函数(clickCollect
)中,我总是将新值设置为state,我不是在等待错误的API响应,该响应会说停止进行更改。在所有情况下,新值都会进入状态。实际上,我setState
只要求UI再次呈现。所以问题是:
for var i in ...
).slice(0)
如果我的数组包含对象,则进行浅表克隆()是否有意义?更改是在数组内部的对象上进行的,因此浅表克隆仍会更改我的状态,就像copy(data = this.state.data
)一样。我的代码经过简化,并且为简化起见,API调用被删去。
这是一个初学者的问题,因此也欢迎使用完全不同的方法。或链接到其他问答。
> 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;
就我个人而言,我并不总是遵循规则,如果您真的了解自己想做的事情,那么我认为这不是问题。
var data = this.state.data.slice(0);
data[index].is_collected = !data[index].is_collected;
this.setState({data: data});
在这种情况下,改变状态并setState
像这样再次调用即可
this.state.data[index].is_collected = !this.state.data[index].is_collected;
this.setState({data: this.state.data});
您应避免更改状态的原因是,如果您引用this.state.data
并setState
多次调用,则可能会丢失数据:
const myData = this.state.data
myData[0] = 'foo'
this.setState({ data: myData })
// do something...
// ...
const someNewData = someFunc()
this.setState({ data: someNewData })
myData[1] = 'bar' // myData is still referencing to the old state
this.setState({ data: myData }) // you lose everything of `someNewData`
如果您真的对此感到担心,请访问immutable.js
问题内容: 所以我有这个: newDealersDeckTotal只是一个数字数组,例如,但是没有给出正确的总数,但是呢?我什至设置了超时延迟,以查看是否可以解决问题。任何明显的还是我应该发布更多代码? 问题答案: 通常是异步的,这意味着在您处于状态时,它尚未更新。尝试将日志放入方法的回调中。状态更改完成后执行:
问题内容: 保持不变,尽管我在函数中调度了一个动作: 输出为NO_AUTH(的初始值) 减速器: 知道为什么吗? 问题答案: 您当前正在直接在未映射到的componentDidMount内部调度: 这应该做的工作: 现在,这将获得authState:
在这种情况下,我更改选择元素并调用数据更新方法。该方法从状态获取值。但是当数据更新时,状态还没有改变。当您再次调用数据更新时,状态已经更新了如何正确进行更新? 反应成分
我猜这可能与从父级打开有关,但我有其他组件,它们内部的状态发生变化,所以我有点困惑,为什么这个组件不尊重它的新状态。 谢谢
所以我有这个: 只是一个数组的数字例如然而没有给出正确的总数,但?我甚至放了一个超时延迟,看看这是否解决了问题。任何明显的还是我应该发布更多的代码?
有一个案例我很困惑。 我有一个对象redux状态:{show:true,creative:{name:'a',tags:[t1,t2,t3]}。此对象已通过“react redux”的“connect”功能映射到道具。 当我改变属性“显示”或“creative.name”时,它确实会触发重新渲染。但是如果我将t0追加到"creative.tags",它就不会运行re-渲染。 我必须分配一个新变量来