0

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.

2
  • 2
    First of, you are calling change_text("Παιξε"); in each click, so it will override all your changes. But in order to let us help you with this, you need to provide more details on your code (like what is questions_size value?) and create a Minimal, Reproducible Example of your current attempt. Commented Jun 3, 2020 at 12:03
  • I edited my answer to include the questions_size variable but to more more accurate this is how many elements my json file has. Ok I will try to add some more data to be able for you to reproduce it. Commented Jun 3, 2020 at 12:11

4 Answers 4

2

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>
Sign up to request clarification or add additional context in comments.

1 Comment

This is such a clever answer :) Thank you!
2
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

Comments

2

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.

CodeSandbox

Comments

1

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

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.