如何在TypeScript中使用useState向数组添加新输入项
Hey there! Let's work through your TypeScript + React form issue step by step. I see you're building a quiz form and want to add new answer fields when clicking the "+ add answer" button—here's how to make that work smoothly while keeping TypeScript happy, plus fix a few missing state bindings in your existing code:
First, let's clean up the type definitions to make things clearer, then implement the add functionality, and finally tie up loose ends with your form inputs.
1. Define a Reusable Type for Answer Items
To avoid repeating the type definition and keep TypeScript happy, create an interface for your answer objects:
// Place this outside your component for reusability interface AnswerItem { correct: boolean; label: string; value: string; id: number; }
Update your useState to use this interface:
const [answers, setAnswers] = useState<AnswerItem[]>([ { correct: false, label: "Answer 1 ...", value: "", id: 0 }, { correct: false, label: "Answer 2 ...", value: "", id: 1 } ]);
2. Create the Add Answer Handler
You can't directly push to the state array (React state is immutable), so we'll create a new array with the existing items plus a new answer. Here's the handler function:
const addAnswer = () => { const newId = answers.length; const newAnswer: AnswerItem = { correct: false, label: `Answer ${newId + 1} ...`, value: "", id: newId }; // Use the functional update form of setAnswers to get the latest state setAnswers(prevAnswers => [...prevAnswers, newAnswer]); };
3. Bind the Handler to Your Button
Attach the addAnswer function to your button's onClick event:
<Button className="addbutton border-0" onClick={addAnswer}>+ add answer </Button>
4. Fix Missing State Bindings for Existing Answers
Right now, your answer inputs and checkboxes don't sync with the answers state—here's how to fix that:
{answers.map((item, index) => { // Update answer text input const handleAnswerTextChange = (e: React.ChangeEvent<HTMLInputElement>) => { setAnswers(prev => { const updatedAnswers = [...prev]; updatedAnswers[index].value = e.target.value; return updatedAnswers; }); }; // Toggle correct answer checkbox const handleCorrectToggle = () => { setAnswers(prev => { const updatedAnswers = [...prev]; updatedAnswers[index].correct = !updatedAnswers[index].correct; return updatedAnswers; }); }; return ( <div key={item.id} className="mb-4"> <div className="row mt-4 justify-content-center"> <Form.Control className="formbg form3" type="text" name="text" placeholder={item.label} value={item.value} onChange={handleAnswerTextChange} /> </div> <div className="row"> <input type="checkbox" id={`correct-${item.id}`} checked={item.correct} onChange={handleCorrectToggle} /> <label htmlFor={`correct-${item.id}`} className="my-2">Good answer</label> </div> </div> ); })}
Key fixes here:
- Added a unique
keyprop to each mapped item (required by React) - Made checkbox IDs unique so labels target the right input
- Bound input values and change handlers to sync with the
answersstate
5. Update the Save Button to Include Answers
Modify your save click handler to log all form data, including answers:
<Button className="registerbutton" block size="lg" type="submit" onClick={() => console.log({ inputTitle, inputQuestion, answers })}>Save</Button>
With these changes, your form will let you add new answer fields, sync all user input to state, and play nicely with TypeScript's type checks.
内容的提问来源于stack exchange,提问作者Coraline Iltchenko

