我有一个父组件<App>
:
constructor() {
super();
this.state = {
transporterPos: 0
}
this.tick = this.tick.bind(this);
}
componentDidMount() {
this.timerId = setInterval(() => this.tick(), 1000);
}
componentWillUnmount() {
clearInterval(this.timerId);
}
tick() {
let transporterPos = this.state.transporterPos;
transporterPos++;
if (transporterPos > 7) {
transporterPos = 0;
}
this.setState({ transporterPos: transporterPos });
}
render() {
return (
<div>
<Staves transporterPos={this.state.transporterPos}/>
</div>
);
}
<Staves>
组件包含多个<Stave>
组件,每个组件包含多个<Note>
组件。每个<Note>
组件都注入一个className
条件,其active
属性为true
:
<div className="noteContainer" onClick={this.handleClick}>
<div className={"note" + (this.props.active ? ' active' : '')}></div>
</div>
handleClick()
是一种切换<Note>
的{{1}}属性的方法。我没有在这里包含所有代码以使其更具可读性。问题是,当点击active
时,虽然其<Note>
属性会立即更改,但“活动”的条件active
给出的样式在之前不可见,直到该组件为在className
方法的下一个“勾号”处重新渲染。换句话说,渲染似乎每1000ms就会发生一次。我希望它能立即发生。我使用setInterval
错了吗?
修改
在回复评论时,这是setInterval
方法(handleClick
中):
<Note>
这会调用handleClick() {
this.props.toggleActive(this.props.pos);
}
中的toggleActive
:
<Stave>
toggleActive(pos) {
this.props.notes[pos].active = !this.props.notes[pos].active;
}
此处是props.notes
的{{1}}的一部分,传递给<App>
(我在此问题中未将其包含在内简洁)。
答案 0 :(得分:1)
toggleActive(pos) {
this.props.notes[pos].active = !this.props.notes[pos].active;
}
未触发重新渲染的原因是因为this.props
直接变异而不是setState
变异。将toggleActive
进一步移动到您可以使用setState
的位置。
如有必要,您可以将该功能作为道具传递给子组件,并通过this.props.toggleActive()
除了不触发重新渲染之外,永远不应该直接变异this.props
的另一个原因是因为只要父级更改状态并将props传递给子级,您的更改就会被覆盖。