简体   繁体   English

基于当前状态的React中的setState

[英]setState in React based on current state

When updating a stateful component in React is it considered a bad practice when a component uses the current state to update the new state. 在React中更新有状态组件时,当组件使用当前状态更新新状态时,它被认为是一种不好的做法。

For example if I have a class that stores whether a filter is open or not in it's state, is one of these options for updating the state more desirable than the other in terms of performance? 例如,如果我有一个类来存储过滤器是否处于打开状态,那么在性能方面,更新状态的其中一个选项是否比另一个更理想?

Option 1: 选项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}
        />
    }
}

Option 2: 选项2:

class Container extends Component {
    state = {
        show: false
    }

    toggleVisibility = () => this.setState({ show: !this.state.show })

    render() {
        <ExternalComponent
            toggleVisibility={this.toggleVisibility}
        />
    }
}

Option 3: 选项3:

class Container extends Component {
    state = {
        show: false
    }

    setShow = (newVal) => this.setState({ show: newVal })

    render() {
        <ExternalComponent
            setShow={this.setShow}
        />
    }
}

There is nothing wrong with a component accessing its own state. 组件访问其自身状态没有任何问题。 Write-only state wouldn't be terribly useful! 只写状态不会非常有用! However, you should be very careful when exposing component state or state-altering methods to other components. 但是,在将组件状态或状态更改方法暴露给其他组件时应该非常小心。 Component state is internal, and should only been touched from outside via a well-considered interface, to prevent your components from becoming an entangled mess. 组件状态是内部的,只能通过经过深思熟虑的界面从外部触摸,以防止组件变得纠结。

In fact, there is an example that is similar to your Example #2 in the React documentation : 实际上,有一个示例与React文档中的示例#2类似:

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')
);

Note a difference from your example, however. 但请注意与您的示例的不同之处。 The toggle method needs to be bound in the constructor, to ensure that this means what you're expecting it to mean. 切换方法需要在构造函数中绑定,以确保this意味着您期望它的含义。

If the wrapping component is the one keeping track of the visibility of the child ExternalComponent , then rather than passing the toggle method into the child component, I would expect the wrapper to render a hide/show affordance of some sort, and then either pass the current visibility into the child component as a prop or selectively render it (note that selective rendering will cause the entire child component to be remounted when it's enabled again, which may be expensive; you may be better off hiding it than tearing it down and recreating it). 如果包装组件是跟踪子ExternalComponent的可见性的那个,那么我不希望将toggle传递给子组件,我希望包装器呈现隐藏/显示某种类型的可供件,然后通过当前对子组件的可见性作为道具或有选择地呈现它(请注意,选择性渲染将导致整个子组件在再次启用时重新安装,这可能很昂贵;您可能最好隐藏它而不是将其拆除并重新创建它)。 That makes the division of concerns clear: the wrapper knows about visibility, and the child component doesn't need to know how or why that decision was made, nor does it need to touch the wrapper's internal state. 这使得关注点分工清晰:包装器知道可见性,子组件不需要知道如何或为什么做出决策,也不需要触及包装器的内部状态。

There is nothing wrong with using the current state's value to determine the new state value. 使用当前状态的值来确定新的状态值没有任何问题。

Option 2 has less code, which kind of appeals to me. 选项2的代码较少,这对我很有吸引力。 However, sometimes I might have to use Option 1 when using a third-party component (eg Semantic UI React modal) and it has show and hide handlers that we have to define. 但是,有时我可能必须在使用第三方组件时使用选项1(例如Semantic UI React模式),并且它具有显示和隐藏我们必须定义的处理程序。

Option 3 is also fine; 方案3也没问题; I would use it for other applications other than this show/hide one (in fact, that one is used pretty much all the time, especially when you have controlled input components). 我会将它用于除此显示/隐藏之外的其他应用程序(事实上,它几乎一直被使用,特别是当你有控制输入组件时)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM