我有一个带有4个按钮的ReactJS菜单组件,它触发我页面的右侧和一堆过滤器,以便在点击时重新加载。
render: function() {
return (
<div className="menu">
{
this.state.items.map(function(menuNode) {
return (
<MenuItem item={menuNode} onClick={this.handleClick} key={menuNode.name} />
);
}, this)
}
</div>
);
},
handleClick: function(selected) {
this.state.items.forEach(function(item) {
item.selected = false;
});
selected.selected = true;
this.setState({
items: this.state.items
});
resetReact.BoxStructure(selected);
resetReact.Filter(selected);
}
resetReact.BoxStructure()
和resetReact.Filter()
会触发setProps()
/ setState()
我的页面中的新内容(BoxStructure)和过滤器组件。
它们在componentDidMount
中设置在每个组件上,如下所示:
var BoxStructure = React.createClass({
...
componentDidMount: function() {
if(this.props.callback)
this.props.callback();
resetReact.BoxStructure = function(selected) {
this.state.boxes = selected.content;
this.setProps({
color: selected.color,
callback: selected.callback,
key: selected.name
});
}.bind(this);
}
});
这样可行,但菜单感觉非常慢,就像它在更改所选菜单项之前等待整个页面加载一样。 BoxStructure需要几秒钟才能加载,这很好并且可以预期,但我不希望菜单在更改所选项目之前等待它。从用户的角度来看,当我点击按钮时感觉没有任何反应。
这可以通过添加setTimeout
1ms:
handleClick: function(selected) {
this.state.items.forEach(function(item) {
item.selected = false;
});
selected.selected = true;
this.setState({
items: this.state.items
});
setTimeout(function() {
resetReact.BoxStructure(selected);
resetReact.Filter(selected);
}, 1);
}
现在菜单立即改变,然后页面可能需要渲染,就像我想要的那样,但问题是为什么我做了一些根本错误的事情?我认为setTimeout
强制重新加载是异步的,但我觉得这不是实现我想要的正确方法,也许ReactJS在某个地方有更好的方法。
答案 0 :(得分:3)
您应该努力提高BoxStructure
和Filter
代码的效率。您可能想要对它们进行分析,打印毫秒时间戳,并执行其他此类操作。
如果您知道这些通话速度很慢,并且您希望向用户提供有关正在发生的事情的反馈,那么您可能希望延迟这些繁重的通话,直到上一次状态更新完成 并呈现 强>
这样做的方法是使用setState的回调:
handleClick: function(selected) {
...
this.setState({
items: ...
}, function() {
resetReact.BoxStructure(selected);
resetReact.Filter(selected);
});
}
来自文档:
第二个(可选)参数是一个回调函数,该函数将在setState完成 并且重新呈现组件 后执行。
同样来自文档:
不要直接改变this.state,因为之后调用setState()可能会替换你所做的突变。把this.state看作是不可变的。
你通过改变this.state然后将它反馈给setState()来避开罚款线。不要那样做。
作为替代方案,您可以在您的州中存储单个selected
索引(0到selectedItem
- 1之间的整数),而不是在每个项目中存储items.length
标志。您只需要更新该单个变量。
此外,为什么您的菜单项目处于开始状态?用户是否允许更改它们?如果答案是否定的,那么你应该将它们放在道具或类常量中。