Home > Software engineering >  Previous state show in react-js
Previous state show in react-js

Time:06-20

I created a question and answer app using react. Four questions are created in four components and each question has three options. The options are show in div. In first question we click an answer(out of any 3 options). Then click next button and show second question (second component). Then select an answer (out of any 3 options) for the second question. And so on till forth question and answer. After clicking previous and next button show the previous/next question and selected answer (state should be persisted for selected answer in all four questions when clicking next and previous button).

Here my main component:

import React from "react";
import Qustionone from "./qustionone";
import Qustiontwo from "./qustiontwo";
import Qustionthree from "./qustionthree";
import Qustionfour from "./qustionfour";

function Questions() {
    return (
        <div>
            <h1>Question and Answer Program</h1>
            <Qustionone />
            <Qustiontwo />
            <Qustionthree />
            <Qustionfour />
            <button>previous</button> <button>next</button>
        </div>
    );
}

export default Questions;

Qustionone.js

import React from "react";

function Qustionone() {
    return (
        <div>
            <p>Qustion 1 ?</p>
            <div>Answer1</div>
            <div>Answer2</div>
            <div>Answer3</div>
        </div>
    );
}

export default Qustionone;

Qustiontwo.js

import React from "react";

function Qustiontwo() {
    return (
        <div>
            <p>Qustion 2 ?</p>
            <div>Answer11</div>
            <div>Answer22</div>
            <div>Answer33</div>
        </div>
    );
}

export default Qustiontwo;

Qustionthree.js

import React from "react";

function Qustionthree() {
    return (
        <div>
            <p>Qustion 3 ?</p>
            <div>Answer111</div>
            <div>Answer222</div>
            <div>Answer333</div>
        </div>
    );
}

export default Qustionthree;

etc...

Here selected class is used to selected div and how write the react proper functionality for these working. I am new to react please help me, thanks in advance

CodePudding user response:

Look at the examples on the Internet something like this: How to Build a Quiz App Using React

CodePudding user response:

I'll try to split my answer into multiple sections, as it would be easier for me to answer the question, and for you to implement. These sections are the following:

  1. Handle questions navigation
  2. Handle answer selection
  3. Rendering question

I will also add a summary at the end with the complete implementation and some ideas for the future refactoring

Handle questions navigation

To implement the navigation among questions we will do the following things:

  1. Create the state selectedQuestionIndex
  2. Create the handler for the navigation buttons clicks
  3. Assign the handler to each of the buttons
// ./questions.jsx
import React, { useState } from 'react';

const MIN_ACTIVE_QUESTION_INDEX = 0;
const MAX_ACTIVE_QUESTION_INDEX = 3;
const DIRECTION_PREV = -1;
const DIRECTION_NEXT = 1;

const limitWithinBoundaries = (val, min, max) => Math.max(min, Math.min(val, max))

function Questions() {
  const [selectedQuestionIndex, setSelectedQuestionIndex] = useState(MIN_ACTIVE_QUESTION_INDEX);

  const onNavigationButtonClick = (direction) => {
    setSelectedQuestionIndex((currentSelectedQuestionIndex) => 
      limitWithinBoundaries(
        currentSelectedQuestionIndex   direction, 
        MIN_ACTIVE_QUESTION_INDEX, 
        MAX_ACTIVE_QUESTION_INDEX
      )
    );
  }
  
  return (
    // ...
    <button onClick={() => onNavigationButtonClick(DIRECTION_PREV)}>previous</button> 
    <button onClick={() => onNavigationButtonClick(DIRECTION_NEXT)}>next</button>
  );
}

Now by clicking on the buttons the selectedQuestionIndex state will be changed within the range - [0, 3] and the component will be rendered on each state change

Handle answer selection

To implement this functionality we just need to create a state for all of the answers and handle the answer selection.

// ...

const replaceAnswerImmutable = (index, answer, answers) => {
  const result = [...answers];
  result[index] = answer;
  return result;
};

function Questions() {
  const [selectedQuestionIndex, setSelectedQuestionIndex] = useState(MIN_ACTIVE_QUESTION_INDEX);
  const [answers, setAnswers] = useState([]);
  // ...

  const onAnswerClick = (event) => {
    // we expect that the answer will be specified as a HTML data-answer atribute
    const answer = event.target.dataset.answer;

    if (!answer) return; 

    setAnswers((currentAnswers) => 
      replaceAnswerImmutable(
        selectedQuestionIndex, 
        answer, 
        currentAnswers
      )
   );
  };

  // ...
}

Not the answer will be recorded for the selected question each time onAnswerClick is executed. onAnswerClick will be used in the section below...

Rendering question

As the markup is similar for each question, we can implement a single component for that.

// question.jsx
import React from 'react';

function Question(props) {
  const { data, onAnswerClick } = props;
  const { question, answers } = data;
  return (
    <div onClick={onAnswerClick}>
      <p>{question}</p>
      {answers.map((answer) => (
        <div key={answer} data-answer={answer}>{answer}</div>
      ))}
    </div>
  );
}

The content of the question and the related answers should be extracted as a dataset.

// ./dataset.js

const QUESTIONS = [
  { question: 'Qustion 1 ?', answers: ['Answer 1', 'Answer 2', 'Answer 3'] },
  { question: 'Qustion 2 ?', answers: ['Answer 1', 'Answer 2', 'Answer 3'] },
  // ...
];

export default QUESTIONS;

Now we just need to render the Question component with the selected question data and the onAnswerClick handler

import React, { useState } from 'react';
import QUESTIONS from './dataset';

// ...

function Questions() {
  const [selectedQuestionIndex, setSelectedQuestionIndex] = useState(MIN_ACTIVE_QUESTION_INDEX);

  const onAnswerClick = (event) => {
    // ...
  };

  const selectedQuestion = QUESTIONS[selectedQuestionIndex];
  
  return (
    <div>
      <Question data={selectedQuestion} onAnswerClick={onAnswerClick} />
      {/* buttons here */}
    </div>
  );
}

Summary

You can find the complete implementation and the working example at this sandbox.

Despite the component works, there is still room for refactoring. As you might notice, the Questions component has a lot of code and I would suggest decomposing it into smaller chunks to improve readability and logic encapsulation. Something like this

import React from 'react';
import Question, { useQuestion } from './question';
import Navigation, { useNavigation } from './navigation';

function Questions() {
  const { selectedQuestionIndex, onNavigationButtonClick } = useNavigation();
  const { onAnswerClick, selectedQuestion } = useQuestion(selectedQuestionIndex);
  
  return (
    <div>
      <Question data={selectedQuestion} onAnswerClick={onAnswerClick} />
      <Navigation onClick={onNavigationButtonClick} />
    </div>
  );
}
  • Related