Michael Angelo
Michael Angelo

Reputation: 49

How to implement previous and next Buttons in React?

I'm trying to build an app in React that will render interview questions from HTML, CSS, JS and React. I've set up a data.js file that is an array with objects inside that hold the Id, language, question and answer.

I've set up buttons for PreviousQuestion, NextQuestion and RandomQuestion.

I'm having trouble writing code for the PreviousQuestion, NextQuestion button. I've tried the following code on both but it doesn't work properly:

    const questions = data.map((item) => item.question);
    
    
    class App extends React.Component {
      state = {
        question: "",
        count: 0,
      };
    
    prevQuestion = () => {
        this.setState({
          count: this.state.count - 1,
          question: questions[this.state.count]
        });
       
      };
    
      nextQuestion = () => {
        this.setState({
          count: this.state.count + 1,
          question: questions[this.state.count]
        });

I press nextQuestion this.state.count is 0 then 1 then 2 and then I press PrevQuestion and this.state.count goes to 3 and only then back to 2 1 ...

Can anyone point me in the right direction on how to solve this so it always increments and decrements properly please?

Upvotes: 2

Views: 5441

Answers (3)

Matt U
Matt U

Reputation: 5118

What's happening is that setState does not update the component state immediately, instead essentially queueing a state transition. See this answer. The answers / comments there also mention that you can use some component lifecycle methods such as componentDidUpdate to do something once a state transition has completed.

As others mentioned, you could update the question index by also adding / subtracting 1 from the state.count. Or, since I also don't think it's necessary to track the current question in the component's state, you could just refer to the question object in the render method:

const questions = data.map(item => item.question);

class Component extends Component {
  constructor () {
    super();

    this.state = {
      count: 0
    }
  }

  nextQuestion () {
    this.setState({ count: this.state.count + 1 });
  }

  previousQuestion () {
    this.setState({ count: this.state.count - 1 });
  }

  render () {
    // Get the question object based on the count in the component state
    const question = questions[this.state.count];

    return (
      <!-- Stuff here -->
      <p>{question}</p>
    );
  }
}

Upvotes: 0

Zahid Hasan
Zahid Hasan

Reputation: 622

Use prevState in setState like the following one.

prevQuestion = () => {
     this.setState(prevState => ({
      count: prevState.count -1
      question: questions[prevState.count -1]
    }));
}

Upvotes: 1

Anis R.
Anis R.

Reputation: 6912

The issue is that inside setState, your state has not changed yet. So in questions[this.state.count], this.state.count still reflects the old value, not the new one.

Therefore, this should fix your issue with prevQuestion:

  prevQuestion = () => {
    this.setState({
      count: this.state.count - 1,
      question: questions[this.state.count - 1]
    });
   
  };

And similarly for nextQuestion.


However, as Emile Bergeron stated in the comments, it would be better to only keep track of the count (i.e. the question index) in the state, and not the question itself. You can always access the relevant question using questions[this.state.count], saving you some headaches.

Upvotes: 2

Related Questions