React 中的 setState 基于当前状态
setState in React based on current state
在 React 中更新有状态组件时,如果组件使用当前状态更新新状态,这被认为是一种不好的做法。
例如,如果我有一个 class 存储过滤器在其状态下是否打开,就性能而言,这些用于更新状态的选项之一是否比另一个更理想?
选项 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}
/>
}
}
组件访问自己的状态没有错。只写状态不会非常有用!但是,在向其他组件公开组件状态或状态更改方法时应该非常小心。组件状态是内部的,只能通过经过深思熟虑的接口从外部进行访问,以防止您的组件变得混乱。
事实上,有一个与您的示例 #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')
);
但是请注意与您的示例的不同之处。 toggle 方法需要在构造函数中绑定,以确保 this
表示您期望的意思。
如果包装组件是跟踪子组件可见性的组件 ExternalComponent
,那么与其将切换方法传递给子组件,我希望包装器呈现一个 [=22= ...最好隐藏它而不是将其拆除并重新创建它)。这使得关注点的划分变得清晰:包装器知道可见性,子组件不需要知道该决定是如何或为什么做出的,也不需要触及包装器的内部状态。
使用当前状态的值来确定新的状态值并没有错。
方案二代码少,比较吸引我。但是,有时我在使用第三方组件(例如 Semantic UI React modal)时可能不得不使用选项 1,并且它具有我们必须定义的显示和隐藏处理程序。
方案三也可以;除了这个 show/hide 以外,我会将它用于其他应用程序(事实上,那个几乎一直都在使用,尤其是当您控制输入组件时)。
在 React 中更新有状态组件时,如果组件使用当前状态更新新状态,这被认为是一种不好的做法。
例如,如果我有一个 class 存储过滤器在其状态下是否打开,就性能而言,这些用于更新状态的选项之一是否比另一个更理想?
选项 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}
/>
}
}
组件访问自己的状态没有错。只写状态不会非常有用!但是,在向其他组件公开组件状态或状态更改方法时应该非常小心。组件状态是内部的,只能通过经过深思熟虑的接口从外部进行访问,以防止您的组件变得混乱。
事实上,有一个与您的示例 #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')
);
但是请注意与您的示例的不同之处。 toggle 方法需要在构造函数中绑定,以确保 this
表示您期望的意思。
如果包装组件是跟踪子组件可见性的组件 ExternalComponent
,那么与其将切换方法传递给子组件,我希望包装器呈现一个 [=22= ...最好隐藏它而不是将其拆除并重新创建它)。这使得关注点的划分变得清晰:包装器知道可见性,子组件不需要知道该决定是如何或为什么做出的,也不需要触及包装器的内部状态。
使用当前状态的值来确定新的状态值并没有错。
方案二代码少,比较吸引我。但是,有时我在使用第三方组件(例如 Semantic UI React modal)时可能不得不使用选项 1,并且它具有我们必须定义的显示和隐藏处理程序。
方案三也可以;除了这个 show/hide 以外,我会将它用于其他应用程序(事实上,那个几乎一直都在使用,尤其是当您控制输入组件时)。