React中对象数组添加元素时状态丢失及报错问题求助
Fixing React Object Array State Update Issues
Let's break down what's going wrong with your state management and fix it step by step:
Key Problems Identified
- Incorrect Initial State: You initialized
estimateas an empty array[], but your desired structure is an object with anitemsarray property. This mismatch breaks value access and state updates. - Broken State Update Logic: When updating
costorservice, you're replacing the entireitemsarray with a single object instead of preserving existing entries and only updating the target one. - Wrong Value Access: You're trying to access
estimate?.items?.["cost"]?.[i]—this assumesitemsis an object with acostarray, butitemsis actually an array of objects where each object hascostandservicekeys.
Corrected Code Implementation
Here's the fixed version with detailed explanations:
import { useState } from 'react'; // Import your Syncfusion components here const YourComponent = () => { // 1. Fix initial state to match your desired structure const [estimate, setEstimate] = useState({ items: [] }); const [numServices, setNumServices] = useState(0); return ( <form> {[...Array(numServices)].map((_, i) => { return ( <div key={i} className="flex justify-between"> <div> <NumericTextBoxComponent format="c2" name={`cost-${i}`} // 2. Correct value access: get cost from the i-th object in items array value={estimate.items[i]?.cost} change={(e) => { // 3. Properly update state without overwriting existing items setEstimate(prevState => { const updatedItems = [...prevState.items]; // Ensure the i-th index exists, or create a new object if not updatedItems[i] = { ...updatedItems[i], cost: e.value }; return { ...prevState, items: updatedItems }; }); }} placeholder='Price' floatLabelType="Auto" data-msg-containerid="errorForCost" /> </div> <div> <DropDownListComponent showClearButton fields={{ value: "id", text: "service" }} name={`service-${i}`} // 2. Correct value access: get service from the i-th object in items array value={estimate.items[i]?.service} change={(e) => { // 3. Properly update state without overwriting existing items setEstimate(prevState => { const updatedItems = [...prevState.items]; // Map selected id to service text (adjust based on your data structure) const selectedService = estimateData?.services.find(s => s.id === e.value)?.service || e.value; updatedItems[i] = { ...updatedItems[i], service: selectedService }; return { ...prevState, items: updatedItems }; }); }} id={`service-${i}`} floatLabelType="Auto" data-name={`service-${i}`} dataSource={estimateData?.services} placeholder="Service" data-msg-containerid="errorForLead" /> <div id="errorForLead" /> </div> </div> ); })} {/* 4. Add default empty object to items when clicking Add */} <button onClick={() => { setNumServices(prev => prev + 1); setEstimate(prev => ({ ...prev, items: [...prev.items, { cost: 0, service: "" }] })); }}>Add</button> </form> ); }; export default YourComponent;
What Each Fix Does
- Initial State Fix: Starting with
{ items: [] }aligns your state with the structure you need, so you can properly access and update theitemsarray. - State Update Logic: Using the functional update form (
setEstimate(prevState => ...)) ensures you're always working with the latest state. We create a copy of theitemsarray, update the specific index, then return the new state—this preserves all existing items while modifying only the one you need. - Value Access:
estimate.items[i]?.costcorrectly targets thecostproperty of the i-th object in theitemsarray, matching your desired data structure. - Add Button Enhancement: Now when you click "Add", we not only increment
numServicesbut also add a default empty object toitems, ensuring the new rendered input has a corresponding entry in the state array.
Additional Notes
If your DropDownListComponent returns the id of the selected service instead of the text (as per your fields={{ value: "id", text: "service" }}), we added logic to map the selected id back to the service text using estimateData?.services.find(). Adjust this part if your data structure or needs are different.
内容的提问来源于stack exchange,提问作者mattr534
相关产品推荐
相关产品推荐

