I am building a website using react where the users should be able to answer questions. some of these questions may have multiple answers so I want the website to dynamically add and remove input fields for these answers. Here is an example to clarify: Initially there will be only 1 input field visible for a question but when the user starts typing in this first input field a second (empty) input field should appear and when he starts typing in the second input field, a third one should appear and so on.
Adding input fields already works fine but empty input fields (when an answer is removed) should also be removed and this is where the problems start.
I am rendering the answers based on the "answers" array using a map function:
{answers.map((answer, index) => (
<div key={index}>
<label htmlFor={`answer${index + 1}`}>{`answer ${index + 1}:`}</label>
<input
type="text"
className="w-full h-10 px-3 text-base placeholder-gray-600 border rounded- lg focus:shadow-outline"
onChange={(e) => handleAnswerChange(index, e.target.value)}
/>
</div>
))}
and this is the "handleanswerchange" function:
const [answers, setAnswers] = useState(['']);
const handleAnswerChange = (index: number, value: string) => {
console.log('Index:', index);
console.log('Value:', value);
setAnswers(prev => {
const updatedAnswers = [...prev];
updatedAnswers[index] = value;
if (value.trim() === '') {
updatedAnswers.splice(index, 1);
}
if (index === updatedAnswers.length - 1 && value.trim() !== '') {
updatedAnswers.push('');
}
return updatedAnswers;
})
setAnswers(prev => [...prev]);
};
useEffect(() => {
console.log(answers);
}, [answers]);
as you can see I am logging the ‘answers’ array. The logs show that the logic is working fine and the array gets updated correctly when an answer is removed but the ui does not reflect these changes.
For example: when I give inputs ‘a’, ‘z’, ‘e’, ‘r’ there are 5 input fields visible. 4 of them contain the inputs and one of them (the last one) is empty. This is correct and what I would expect. When I remove the content of the second input field (in this case ‘z’), this input field should be removed. The array that gets logged is [‘a’,’e’,’r’,”]. This is also correct but the ui does not reflect this array.
Instead, the now empty, second input field remains visible and the empty input field at the end gets removed. I tried using a combination of index and answer as the key attribute for the div, I have tried using uuidV4 to generate unique keys, I have tried rewriting the ‘handleanswerChange’ function about a dozen time, … Nothing seems to work, so I hope one of you guys can help me out. Thanks in advance!
2
Answers
The only issue you had is regarding for omitting
value
attribute off theinput
element. Of course it won’t work if you don’t track the state in theinput
element.Here is my complete code, you can use it in some React playground as well.
Off the question itself, you will also counter a bug when you just have 1 input, and simply write the "space" char on this
input
because you will the delete the input.That said you should modify a bit the logic of the
handleAnswerChange
:here is the thing:
The problem is you are looking in the wrong place, to add a new input when there is value in the preview one, all seems good.
Now here is the answer you have to make to yourself: Where do I have to look to decide if I need to remove the last element?
The answer is: the one before the last input
If this is empty, remove the last position in the array
Advice: Avoid mixing logic, at least when you are starting, React can be a little messy.