Search code examples
javascriptnode.jsreactjsredux

display one question on radio button change and submit the user answer after every 3 questions react


I am new to React, I have a set of random 120 questions from which every time 3 questions are shown to user, and when all 3 questions are filled user submit and then next set of 3 questions loads. I want to show 1 question out of 3 and on every radio button checked show next question and when the 3 questions are answered submit button shows next set of question.

const Quiz = () => {
    const {questions, quiz, options} = useSelector((state) => state.quiz);
    
    const dispatch = useDispatch();
    const history = useHistory();
    const classes = useStyles();
    
   
// this is to get thel questions from the history coming from redux store.
    useEffect(() => {
        if (!questions) {
            dispatch(fetcQuestions(history));
          
        }

    }, []);

      const handleRadioChange = (number, event) => {
        let currentSelection = questions.find(question => question.number === number);
        console.log(currentSelection + "radio selected");
        currentSelection.value = event.target.value;
        console.log(currentSelection.value + "calculate score");
    };

    const handleSubmit = (event) => {
        event.preventDefault();
        }
    };
    return (
        
        !questions?.length ? <CircularProgress /> : (
                     <form onSubmit={handleSubmit}>

                    {questions.map((question) => (
                        <FormControl component="fieldset" key={question.number} className={classes.formControl}>
                            <FormLabel component="legend">{question.question}</FormLabel>
                            <RadioGroup aria-label="quiz" name="quiz" value={question.value} onChange={(e) => handleRadioChange(question.number, e)}>
                                {options.map((option) => 
                                    <FormControlLabel key={option.number} value={option.number} control={<Radio />} label={option.label} />
                                    
                               )}
                            </RadioGroup>
                        </FormControl>
                        

                    ))}

                    <Button type="submit" variant="outlined" color="primary" className={classes.button}>
                        Submit
                </Button>
              
                </form>
           
        )
    );
};

Any help will be appreciated. Thank You.


I have attempted this by adding 2 states but the problem is I am not able to match the question number with the curent ques no

const Quiz = () => {
    const {questions, quiz, options} = useSelector((state) => state.quiz);
    
    const [current_question, setCurrentQuestion] = useState();
    console.log(current_question[number] + "1q");
    
   
    const dispatch = useDispatch();
    const history = useHistory();
    const location = useLocation();
    const classes = useStyles();
    

// this is to get thel questions from the history coming from redux store.
    useEffect(() => {
        if (!questions) {
            dispatch(fetcQuestions(history));
          
         
        }

    }, []);

      const handleRadioChange = (number, event) => {
        let currentSelection = questions.find(question => question.number === number);
        console.log(currentSelection + "radio selected");
        currentSelection.value = event.target.value;
        console.log(currentSelection.value + "calculate score");
        let new_current_questions = Math.min(
            current_question + 1,
            questions.length - 1
          );
          console.log(new_current_questions);
        setCurrentQuestion(new_current_questions);
    };

    const handleSubmit = (event) => {
        event.preventDefault();
        
    };
    return (
        
        !questions?.length ? <CircularProgress /> : (
            <Grid className={classes.container} container alignItems="stretch" spacing={1}>
             
                <form onSubmit={handleSubmit}>
                   
                    {questions.map((question) => (
                        
                        <FormControl component="fieldset" key={question.number} className={classes.formControl} data-hidden={question.number !== current_question[question.number]}>
                            <FormLabel component="legend">{question.question}</FormLabel>
                            <RadioGroup aria-label="quiz" name="quiz" value={question.value} onChange={(e) => handleRadioChange(question.number, e)}>
                                {options.map((option) => 
                                    <FormControlLabel key={option.score} value={option.score} control={<Radio />} label={option.label} />
                                    
                               )}
                            </RadioGroup>
                        </FormControl>
                        

                    ))}

                    <Button type="submit" variant="outlined" color="primary" className={classes.button}>
                        Submit
                </Button>
              
                </form>
            </Grid>
        )
    );
};



export default Quiz;

I added data-hidden field to display none; so that current question is only shown but all 3 questions are coming. I think the problem is that i am not getting the array of ques num. Please help


Solution

  • In your attempt you don't set an initial value for your current_question state, so when you go to increment it, you're doing the operation: undefined + 1.

    You also need to conditionally render the questions, either by filtering them beforehand or when you map them to JSX:

    const Quiz = () => {
        const { questions, quiz, options } = useSelector((state) => state.quiz);
        
        const [currentQuestion, setCurrentQuestion] = useState(0);
        console.log(currentQuestion[number] + "1q");
        
        const dispatch = useDispatch();
        const history = useHistory();
        const location = useLocation();
        const classes = useStyles();
        
    
        // this is to get the questions from the history coming from redux store.
        useEffect(() => {
            if (!questions) {
                dispatch(fetchQuestions(history));
            }
        }, []);
    
          const handleRadioChange = (number, event) => {
            let currentSelection = questions.find(question => question.number === number);
            console.log(currentSelection + "radio selected");
            currentSelection.value = event.target.value;
            console.log(currentSelection.value + "calculate score");
            // Set the new question count based on the current one
            setCurrentQuestion((current) => {
              return Math.min(
                current + 1,
                questions.length - 1
              );
            });
        };
    
        const handleSubmit = (event) => {
            event.preventDefault();
        };
        return (
            !questions?.length ? <CircularProgress /> : (
                <Grid className={classes.container} container alignItems="stretch" spacing={1}>
                    <form onSubmit={handleSubmit}>
                        {/* Only show the question if it's index is less than or equal to the current question */}
                        {questions.map((question, index) => (index <= currentQuestion ? (
                            <FormControl component="fieldset" key={question.number} className={classes.formControl} data-hidden={question.number !== current_question[question.number]}>
                                <FormLabel component="legend">{question.question}</FormLabel>
                                <RadioGroup aria-label="quiz" name="quiz" value={question.value} onChange={(e) => handleRadioChange(question.number, e)}>
                                    {options.map((option) => 
                                        <FormControlLabel key={option.score} value={option.score} control={<Radio />} label={option.label} />
                                   )}
                                </RadioGroup>
                            </FormControl>
                        ) : null))}
                        <Button type="submit" variant="outlined" color="primary" className={classes.button}>
                            Submit
                    </Button>
                    </form>
                </Grid>
            )
        );
    };
    
    export default Quiz;