Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Radio button keeps re-rendering when clicked

I’m fetching data from an API, and I map over it in order to generate 5 groups of radio buttons. Everything works fine, except for the fact that when I click on any of the input radio buttons, it seems to re-render the entire component or something, as you can see below (this is only one of the groups, but it happens and affects all of them):

enter image description here

Here’s the code:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

import { useState } from "react";
import { nanoid } from "nanoid";

export default function Question({ data }) {
    const [userSelections, setUserSelections] = useState({
        question0: "",
        question1: "",
        question2: "",
        question3: "",
        question4: "",
    })

    function handleSelection(event) {
        const {name, value} = event.target

        setUserSelections(prevSelection => {
            return {
                ...prevSelection,
                [name]: value
            }
        })
    }

    const renderQuestionBlocks = data.map(({question, correct_answer, incorrect_answers, uniqueQuestionId}, questionIndex) => {
        const allAnswers = [...incorrect_answers, correct_answer].sort((a, b) => 0.5 - Math.random())
        data.uniqueQuestionId = nanoid()

        return (
            <form className={`question--container question${questionIndex}`} key={data.uniqueQuestionId}>
                <p>{question.replace(/&quot;/g, '"').replace(/&#039;/g, "'")}</p>
                
                {allAnswers.map((answer, answerIndex) => {
                    data[questionIndex].uniqueAnswerId = nanoid()
                    
                    return (
                    <div 
                        key={data[questionIndex].uniqueAnswerId}
                        className={`choice--container question${questionIndex}`}
                    >
                        <input 
                            type="radio"
                            name={`question${questionIndex}`}
                            id={`question${questionIndex}option${answerIndex}`}
                            value={answer}
                            checked={userSelections[`question${questionIndex}`] === answer}
                            onChange={handleSelection}
                        />
                        <label htmlFor={`question${questionIndex}option${answerIndex}`}>{answer.replace(/&quot;/g, '"').replace(/&#039;/g, "'")}</label>
                    </div>
                    )
                })}             
            </form>
        )
    })
    
    return (
        <div className="questions--container">
            {renderQuestionBlocks}
            <button>Check answers</button>
        </div>
    )
}

>Solution :

it seems to re-render the entire component or something

Updating state re-renders a component. This is expected and correct (and fundamentally necessary) behavior in React. But… What does your component do when it renders?

It randomly sorts the values:

const allAnswers = [...incorrect_answers, correct_answer].sort((a, b) => 0.5 - Math.random())

It sounds like either that sort shouldn’t be random, or should be randomized outside the scope of this component, or that randomization should itself be persisted in state so you can re-use it on each render.

For example, if you just need a random number for the component then you can generate one and keep it in state:

const [randonNumber] = useState(Math.random());

This will randomly generate a number, but won’t re-generate one on every render. Then you can consistently use the same randomly generated number:

const allAnswers = [...incorrect_answers, correct_answer].sort((a, b) => 0.5 - randonNumber)
    
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading