Reputation: 65
I have a counter that is the index of my array, on every button click the next element is showing. What I want to achieve is I want a specific text to show on the beginning and when index becomes 0 again and a different text on the in between numbers. Here is my code till now, the text stays the same but I am not sure what is wrong.
function App() {
const questions_size = Data.length;
const [num, setNum] = useState(0);
const current = Data[num].content;
const [buttonText, setButtonText] = useState("Παιξε");
const change_text = (text) => setButtonText(text);
const callTwoFunc = () => {
setNum(num + 1);
setButtonText("Επομενο");
}
return (
<div style={{ display: 'flex' }}>
<Button variant="contained" color="primary" onClick={() => { num < questions_size - 1 ? callTwoFunc() : setNum(0); change_text("Παιξε"); }}>{buttonText}</Button>
<Card className={classes.root}>
<CardContent>
<Typography variant="body1" gutterBottom>
<p style={{ fontFamily: 'Tangerine, serif', fontSize: '35px', textShadow: '4px 4px 4px #aaa' }}>{current}</p>
</Typography>
</CardContent>
</Card>
</div>
);
}
export default App;
For now it's only saying "Παιξε" but i want it become "Επόμενο" after my first click, and then when num becomes zero to become "Παίξε" again.
Upvotes: 0
Views: 1120
Reputation: 10520
As I said earlier the actual part that ruined your code is calling change_text("Παιξε");
in each click, so it will override all your change, so the best practice to overcome such an issue is to make your onClick
function more generic. So you have to pass all the logic to your callTwoFunc()
function. One of the practices can be using traditional if-else
in your function.
So your final code should be something like this:
const callTwoFunc = () => {
if (num < questions_size - 1) {
setNum(num + 1)
change_text('Επομενο')
} else {
setNum(0)
change_text('Παιξε')
}
}
return (
<Button
variant='contained'
color='primary'
onClick={() => {
callTwoFunc()
}}
>
{buttonText}
</Button>
)
Working demo:
I didn't know what is the actual Data
is so I just mocked it with empty strings.
Upvotes: 2
Reputation: 295
import React, {useState} from "react";
import "./styles.css";
export default function App() {
const Data = [{content: ""},{content: ""}]
const questions_size = Data.length;
const [num, setNum] = useState(0);
// const current = Data[num].content;
const [buttonText, setButtonText] = useState("Παιξε");
const change_text = (text) => setButtonText(text);
const callTwoFunc = () => {
setNum(num + 1);
change_text("Επομενο")
}
const handleClick = () => {
console.log('click',num < questions_size - 1);
if(num < questions_size - 1){
callTwoFunc()
}
else{
console.log('ding');
setNum(0);
change_text("Παιξε");
}
}
return (
<div className="App">
<button variant="contained" color="primary" onClick={handleClick}>{buttonText}</button>
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
Try doing like this...guess it will work
Upvotes: 2
Reputation: 2877
By doing like so
num < questions_size - 1 ? callTwoFunc() : setNum(0); change_text("Παιξε");
the operator actually goes like num < questions_size - 1 ? callTwoFunc() : setNum(0);
while after it and in any case change_text("Παιξε");
will run. change the opertor to standart if
syntax, for having a block to each case instead just one expression
if (num < questions_size - 1) callTwoFunc()
else { setNum(0); change_text("Παιξε"); }
or use comma operator - Javascript - Ternary Operator with Multiple Statements
Upvotes: 1
Reputation: 9002
The problem is the change_text('Παιξε');
part of your onClick
function of the Button:
onClick={() => {
num < questions_size - 1 ? callTwoFunc() : setNum(0);
change_text('Παιξε');
}}
It will always change the button to Παιξε. It is easier to move that logic into callTwoFunc
:
const callTwoFunc = () => {
setNum(prev => {
if(prev < questions_size - 1) {
return prev + 1;
} else {
return 0;
}
})
}
And for the button as there are only two states, it is easier to do it directly instead of using state:
<Button>{num === 0 ? "Παιξε" : "Επομενο" }</Button>
Upvotes: 2