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);
}
};
CodePudding user response:
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>
{counter}
<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>
{counter}
<button onClick={() => increase()}>Increase</button>
{components[counter]}
</div>
);
}
CodePudding user response:
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.