当更新React中的有状态组件时,当组件使用当前状态更新新状态时,它被认为是一种不好的做法。
例如,如果我有一个类来存储过滤器是否处于打开状态,那么在性能方面更新状态的选项之一是否比另一个更理想?
选项1:
class Container extends Component {
state = {
show: false
}
show = () => this.setState({ show: true })
hide = () => this.setState({ show: false })
render() {
<ExternalComponent
show={this.show}
hide={this.hide}
/>
}
}
选项2:
class Container extends Component {
state = {
show: false
}
toggleVisibility = () => this.setState({ show: !this.state.show })
render() {
<ExternalComponent
toggleVisibility={this.toggleVisibility}
/>
}
}
选项3:
class Container extends Component {
state = {
show: false
}
setShow = (newVal) => this.setState({ show: newVal })
render() {
<ExternalComponent
setShow={this.setShow}
/>
}
}
答案 0 :(得分:7)
组件访问自己的状态没有任何问题。只写状态不会非常有用!但是,在将组件状态或状态更改方法暴露给其他组件时应该非常小心。组件状态是内部的,只能通过经过深思熟虑的界面从外部触摸,以防止组件陷入混乱。
事实上,有一个示例与您的示例#2 in the React documentation类似:
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// This binding is necessary to make `this` work in the callback
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('root')
);
请注意,与您的示例有所不同。切换方法需要在构造函数中绑定,以确保this
表示您期望它的含义。
如果包装组件是跟踪子ExternalComponent
的可见性的那个,那么我不希望将包装器传递给子组件,我希望包装器呈现一些隐藏/显示的功能。排序,然后将当前可见性作为道具传递给子组件或有选择地渲染它(请注意,选择性渲染将导致整个子组件再次启用时重新安装,这可能很昂贵;您可能最好隐藏它比撕毁它并重新创造它)。这使得关注点分工清晰:包装器知道可见性,子组件不需要知道做出决策的方式或原因,也不需要触及包装器的内部状态。
答案 1 :(得分:1)
使用当前状态的值来确定新的状态值没有任何问题。
选项2的代码较少,这对我很有吸引力。但是,有时我可能必须在使用第三方组件时使用选项1(例如语义UI反应模式),并且它具有显示和隐藏我们必须定义的处理程序。
选项3也没问题;我会将它用于除此显示/隐藏之外的其他应用程序(实际上,它几乎一直被使用,特别是当你有控制输入组件时)。