0

I have two buttons, one increases the counter and one decreases. Each time the counter changes, the component is to change. I have tried to create both functions so I can click either button and loop through each available component (3 components).

The expected function is to display one component at a time and to cycle through them using the buttons.

The increase function almost works, but I don't know why. The decrease function does not work. Code Sandbox.

const increase = () => {
    if (counter < 3) {
      setCounter(++counter);
      console.log(counter);
    } else if (counter === 3) {
      setCounter(1);
      setShow1(!show1);
      console.log(counter);
    }
    if (counter === 2) {
      setShow2(!show2);
    }
    if (counter === 3) {
      setShow3(!show3);
    }
  };

  const decrease = () => {
    if (counter === 0) {
      setCounter(3);
      setShow3(!show3);
      console.log(counter);
    } else if (counter < 3) {
      setCounter(--counter);
      console.log(counter);
    }
    if (counter === 2) {
      setShow2(!show2);
    }
    if (counter === 1) {
      setShow1(!show1);
    }
  };
2
  • 1
    What is the expected behavior? What do you mean by "component is to change"? Please elaborate. Commented Jul 5, 2022 at 12:58
  • I've edited my question. I mean that only one div is to be shown at a time. When the buttons are clicked, the div is changed to the next or to the previous. Commented Jul 5, 2022 at 13:14

2 Answers 2

3

you can do something like this

export default function App() {
  let [counter, setCounter] = useState(0);

  const increase = () => {
    setCounter(c => (c + 1) % 3)
  };

  const decrease = () => {
    setCounter(c => (c - 1 + 3) % 3)
  };

  return (
    <div>
      <button onClick={() => decrease()}>Decrease</button>
      &nbsp;{counter}&nbsp;
      <button onClick={() => increase()}>Increase</button>
      {counter === 0 && <div className="red" /> }
      {counter === 1 && <div className="blue" /> }
      {counter === 2 && <div className="pink" /> }
    </div>
  );
}

or

import "./styles.css";
import { useState } from "react";

export default function App() {
  let [counter, setCounter] = useState(0);

  const components = [ <div className="red" />, <div className="blue" />, <div className="pink" />]

  const increase = () => {
    setCounter(c => (c + 1) % components.length)
  };

  const decrease = () => {
    setCounter(c => (c - 1 + components.length) % components.length)
  };

  return (
    <div>
      <button onClick={() => decrease()}>Decrease</button>
      &nbsp;{counter}&nbsp;
      <button onClick={() => increase()}>Increase</button>
      {components[counter]}
    </div>
  );
}

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you very much! I used the first example. It's brilliantly simple. Could you please explain the logic that you used for the decrease function? As I see it, it returns the same answer as (c - 1).
@paq it's pretty simple actually for example if c === 1 it-s 1 - 1 + 3 = 3 % 3 === 0, if it's 0 is 0 -1 +3 = 2 % 3 = 2 and so on
0

Your counter is a state property. When updating a state property using its previous value (like incrementing/decrementing by 1), the callback argument of the state setter must be used.

This is due to the asynchronous nature of setState.
https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous

Also you cannot depend on the value of counter for your setShow1, as it may not be the latest value of counter.

You can use the following code:

increase = () => {
    setState((state)=>{
        let counter;
        if(state.counter < 3) {
            counter = state.counter + 1;
        } else if(state.counter == 3) {
            counter = 1;
        }
        let show1 = (counter==1)? !state.show1: state.show1;
        let show2 = (counter==2)? !state.show2: state.show2;
        let show3 = (counter==3)? !state.show3: state.show3;

        return {counter, show1, show2, show3 };
    });
}

And similarly for decrease.

I don't think the show1, show2 & show3 properties are necessary though.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.