I’m developing a teacher dashboard for creating quizzes, where teachers can add questions and customize the number of answer options from 2 to 10. The inputs for these options are dynamically generated based on the teacher’s selection. However, I’m struggling to efficiently gather these input values as options into an array. I’m using React.js. Any suggestions on how to solve this issue effectively?
what i currently do is this :
import React, { useEffect } from "react";
import { useState } from "react";
import StartMakingTheExamStyle from "../../Styles/StartMakingTheExam.module.css";
// http://localhost:9000/quizzes
function StartMakingTheExam() {
const [howManyAnswers, setHowManyAnswers] = useState(4);
const [question, setQuestion] = useState("");
const [point, setPoint] = useState("");
const [correctAnswer, setCorrectAnswer] = useState(null);
const [possbleAnswers, setPossbleAnswers] = useState([]);
//i ghather the options through this function
function possbleAnswersHandling(index, text) {
const newOptions = [...possbleAnswers];
newOptions[index] = text;
setPossbleAnswers(newOptions);
}
// this effect is just for preventing teachers to generate les thatn 2 or more than 10 options
useEffect(() => {
if (howManyAnswers > 10) {
setHowManyAnswers(2);
return;
}
if (howManyAnswers < 2) {
setHowManyAnswers((prev) => prev + 1);
return;
}
}, [howManyAnswers]);
return (
<div className={StartMakingTheExamStyle.TeacherMakeTheExamParent}>
<form action="">
<label className="make-exam-lable" htmlFor="question">
Question
</label>
<input
type="text"
id="question"
placeholder="the question here..."
value={question}
onChange={(e) => setQuestion(e.target.value)}
/>
<label htmlFor="number-of-answers">Number Of Possble Answers</label>
<input
value={howManyAnswers}
type="number"
id="number-of-answers"
onChange={(e) => {
setHowManyAnswers(Number(e.target.value));
dispatch({
type: "numberOfOptionsChanged",
payload:
Number(e.target.value) >= 2 && Number(e.target.value) <= 10
? Number(e.target.value)
: 2,
});
}}
/>
<hr />
{/* -----------------HERE I RENDER THE INPUTS */}
<div className={StartMakingTheExamStyle.teacherQuestionItems}>
{[...Array(howManyAnswers)].map((_, index) => {
return (
<div key={renderedElemensKey(index)}>
<label id={`possble-answer${index + 1}}`}></label>
<input
id={`possble-answer${index + 1}}`}
type="text"
value={possbleAnswers}
onChange={(e) => {
const value = e.target.value;
setPossbleAnswers(value);
}}
onBlur={(e) => {
const value = e.target.value;
possbleAnswersHandling(index, value);
}}
/>
<input
type="radio"
checked={correctAnswer === index + 1}
onChange={() => {
setCorrectAnswer(Number(index + 1));
}}
/>
</div>
);
})}
</div>
<button>Next</button>
</form>
</div>
);
}
export default StartMakingTheExam;
I’m currently adding new items into an array based on their index, but I don’t believe my implementation is efficient. I’m encountering issues with using the onBlur event because if I call the function inside onChange, it seems the app gets re-rendered, and I need to click again on the input to write the second character and so on until the sentence is completed. This is the main reason why I think my approach is not correct. Another issue is that if I skip the first input and move to the second one to fill it, the first input will put an empty string into the array, and even if I click on it to rewrite its value, I cannot. I’m confused about this problem as I’ve never gathered information from a rendered list of inputs before, and I don’t have any idea how to do it correctly and efficiently.