Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

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:

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:

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

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

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

Option 3:

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

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

    render() {
        <ExternalComponent
            setShow={this.setShow}
        />
    }
}
like image 397
Onaracs Avatar asked Feb 27 '17 20:02

Onaracs


People also ask

What is the use of setState in react?

The setState () method enqueues all of the updates made to the component state and instructs React to re-render the component and its children with the updated state. Always use the setState () method to change the state object, since it will ensure that the component knows it’s been updated and calls the render () method.

How to change the state of a React component?

Whenever the state changes, React re-renders the component to the browser. Before updating the value of the state, we need to build an initial state setup. Once we are done with it, we use the setState () method to change the state object. It ensures that the component has been updated and calls for re-rendering of the component.

How to change the state of the component using setState ()?

It ensures that the component has been updated and calls for re-rendering of the component. Syntax: We can use setState() to change the state of the component directly as well as through an arrow function. setState({ stateName : updatedStateValue }) // OR setState((prevState) => ({ stateName: prevState.stateName + 1 }))

What is state in ReactJS?

This article will help you get familiar with a very important concept of React, the state. React State holds the data for a component. The component, in turn, returns the data contained within the state to the output. What Is ‘State’ in ReactJS?


2 Answers

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:

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.

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). 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.

like image 80
S McCrohan Avatar answered Sep 30 '22 19:09

S McCrohan


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. However, sometimes I might have to use Option 1 when using a third-party component (e.g. Semantic UI React modal) and it has show and hide handlers that we have to define.

Option 3 is also fine; 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).

like image 31
nbkhope Avatar answered Sep 30 '22 18:09

nbkhope