skip to Main Content

I’m building a simple react application and I want to update the state of a component based on certain conditions. Currently, I’m using a hardcoded solution that works, but it seems too complicated and I want to know if there is a simpler way to achieve the same result.

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
      value: 'initial'
    };
  }

  handleClick() {
    this.setState((prevState) => {
      if (prevState.count === 0) {
        return { count: prevState.count + 1, value: 'clicked once' };
      } else if (prevState.count === 1) {
        return { count: prevState.count + 1, value: 'clicked twice' };
      } else {
        return { count: prevState.count + 1, value: 'clicked many times' };
      }
    });
  }

  render() {
    return (
      <div>
        <p>{this.state.value}</p>
        <button onClick={() => this.handleClick()}>Click me</button>
      </div>
    );
  }
}

This works, but it’s not scalable and becomes hard to manage as the number of conditions increases.

2

Answers


  1. You can use the conditional operator.

    this.setState(prevState => ({count: prevState.count + 1, value: 
    'clicked ' + (prevState.count === 0 ? 'once' : prevState.count === 1 ? 'twice' : 'many times')}));
    
    Login or Signup to reply.
  2. You are experiencing stress because your value state is an anti-pattern. It is a derivative of count and should not have state of its own. That is to say count is your single source of truth

    function App() {
      const [count, setCount] = React.useState(0)
      const onClick = event => setCount(c => c + 1)
      return <div>
        <button onClick={onClick} children="click" />
        <p>
          { count == 0 
          ? "initial" // derived from count
          : count == 1
          ? "clicked once"
          : count == 2
          ? "clicked twice"
          : "clicked many times"
          }
        </p>
      </div>
    }
    
    ReactDOM.createRoot(document.querySelector("#app")).render(<App />)
    <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <div id="app"></div>

    As a class-based component, that might look like this –

    class App extends React.Component {
      state = { count: 0 }
      onClick = e =>  this.setState(s => ({ count: s.count + 1 }))
      render() {
        return <div>
          <button onClick={this.onClick} children="click" />
          <p>
            { this.state.count == 0 // derived from count
            ? "initial"
            : this.state.count == 1
            ? "clicked once"
            : this.state.count == 2
            ? "clicked twice"
            : "clicked many times"
            }
          </p>
        </div>
      }
    }
    
    ReactDOM.createRoot(document.querySelector("#app")).render(<App />)
    <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <div id="app"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search