Javascript 反应-如何管理多个动态创建的受控输入的状态?
所以在我的例子中,我映射到一个返回的用户对象,并为每个用户创建一个表单。每个表单表示每个用户的“添加工作小时数”输入集 例如,这里是我返回的用户数组的缩写版本:Javascript 反应-如何管理多个动态创建的受控输入的状态?,javascript,reactjs,Javascript,Reactjs,所以在我的例子中,我映射到一个返回的用户对象,并为每个用户创建一个表单。每个表单表示每个用户的“添加工作小时数”输入集 例如,这里是我返回的用户数组的缩写版本: employees: [ { name: Jason Doe, email: jdoe@gmail.com, }, { name: Susan Doe, email: sdoe@gmail.com, }, { name:
employees: [
{
name: Jason Doe,
email: jdoe@gmail.com,
},
{
name: Susan Doe,
email: sdoe@gmail.com,
},
{
name: Jon Doe,
email: jdoe@gmail.com
}
]
从这些用户中,我在React组件中为每个用户创建了一个单独的“添加小时”表单,如下所示:
{employees.map((employee, i) => (
<EmployeeTableItem key={i}>
<p>{employee.fullName}</p>
<input type="number" placeholder="Reg. Hours" />
<input type="number" placeholder="OT Hours" />
<input type="date" placeholder="From Date" />
<input type="date" placeholder="To Date" />
<div>
<AddHoursButton bordercolor="secondaryColorLight" type="button">
Add Hours
</AddHoursButton>
</div>
</EmployeeTableItem>
))}
更新功能:
const updatePostData = (value, key) => {
setPostData(prevData => {
return {
...prevData,
[key]: value
};
});
};
投入:
<input value={postData.firstName} onChange={(e) => updatePostData(e.target.value, 'firstName')} />
<input value={postData.lastName} onChange={(e) => updatePostData(e.target.value, 'lastName')} />
<input value={postData.email} onChange={(e) => updatePostData(e.target.value, 'email')} />
updatePostData(e.target.value,'firstName')}/>
updatePostData(e.target.value,'lastName')}/>
updatePostData(e.target.value,'email')}/>
这个例子非常简单明了。我已经知道需要在组件和状态中创建的输入类型。例如,用户注册表单。我已经知道我需要什么输入,所以我可以将它们的值硬编码到状态
在某种程度上,我倾向于这是一个不需要动脑筋的人,我认为我在思考如何做到这一点。不管怎样,我感谢您的洞察力和建议 您可以为每个输入和员工使用一个id,因此当您将数据设置为状态时,它将通过id保存在该状态
employees: [
{
id: 1,
name: Jason Doe,
email: jdoe@gmail.com,
},
{
id: 2,
name: Susan Doe,
email: sdoe@gmail.com,
},
{
id: 3,
name: Jon Doe,
email: jdoe@gmail.com
}]
所以状态就是对象的对象。您可以尝试将初始状态设置为空对象吗
const [postData, setPostData] = useState({})
在更改时传递id并使用它将其设置为状态
<input id={postData.id} value={postData.firstName} onChange={(e) => updatePostData(e.target.value, postData.id, 'firstName')} />
<input id={postData.id} value={postData.lastName} onChange={(e) => updatePostData(e.target.value, postData.id, 'lastName')} />
<input id={postData.id} value={postData.email} onChange={(e) => updatePostData(e.target.value, postData.id, 'email')} />
最后,我通过
useffect()
在mount上动态初始化了postData
状态。在useffect()。以下是动态创建状态对象的实现:
const AddHours = ({ employees }) => {
const [postData, setPostData] = useState({);
useEffect(() => {
let postDataObj = {};
employees.forEach(employee => {
postDataObj = {
...postDataObj,
[employee._id]: {
regHours: 0,
otHours: 0,
fromDate: 'mm/dd/yy',
toDate: 'mm/dd/yy'
}
};
});
setPostData(postDataObj);
}, [employees]);
}
在forEach
函数中的employees
数组的每次迭代之后,我使用employeed创建一个对象。\u id
并在该对象内部设置捕获输入所需的键。每个员工
对象都可以由每个员工
数据附带的\u id
引用。在每次循环之后,新创建的对象被添加到postDataObj
,为了保存该对象的早期版本,我将其展开(…postDataObj
)以获得一个浅拷贝
当forEach
功能完成时,postDataObj
通过setPostData(postDataObj)
设置为状态。此效果将在员工
道具更改时运行
最后,这就是postData
的console.log
在所有这些之后的样子:
5e3db85dfe149131cd7c9c77: {regHours: 0, otHours: 0, fromDate: "mm/dd/yy", toDate: "mm/dd/yy"}
5e3db870fe149131cd7c9c78: {regHours: 0, otHours: 0, fromDate: "mm/dd/yy", toDate: "mm/dd/yy"}
5e3db87ffe149131cd7c9c79: {regHours: 0, otHours: 0, fromDate: "mm/dd/yy", toDate: "mm/dd/yy"}
5e3db896fe149131cd7c9c7a: {regHours: 0, otHours: 0, fromDate: "mm/dd/yy", toDate: "mm/dd/yy"}
5e5d379c03e7d104bb98fa39: {regHours: 0, otHours: 0, fromDate: "mm/dd/yy", toDate: "mm/dd/yy"}
5e5d395503e7d104bb98fa3a: {regHours: 0, otHours: 0, fromDate: "mm/dd/yy", toDate: "mm/dd/yy"}
5e5d3dcd5cd2850882c105ba: {regHours: 0, otHours: 0, fromDate: "mm/dd/yy", toDate: "mm/dd/yy"}
现在我有了处理组件内受控输入所需的对象
这是输入将用来更新状态的updatePostData
函数:
const updatePostData = (id, key, value) => {
setPostData(prevData => {
return {
...prevData,
[id]: {
...postData[id],
[key]: value
}
};
});
};
这很简单。输入传入一个id、key、value
参数,函数将使用该参数查找员工。_id
在postDataObj
对象中输入,而[key]:value
显然是从输入onChange()
传入的值和目标键。请注意,prevData
被扩展到新对象中,然后重新保存到状态。这对于保持不变的值是必要的,但我们也在创建状态的新副本,而不是直接对其进行变异。…postData[id]
正在传播员工对象的上一个键/值。这将通过更新来保持其输入数据对象
最后,以下是输入:
{ Object.keys(postData).length !== 0 ?
{employees.map((employee, i) => (
<EmployeeTableItem>
<p>{employee.fullName}</p>
<input
value={postData[employee._id].regHours}
onChange={e =>
updatePostData(employee._id, 'regHours', e.target.value)
}
type="number"
placeholder="Reg. Hours"
/>
<input
value={postData[employee._id].otHours}
onChange={e =>
updatePostData(employee._id, 'otHours', e.target.value)
}
type="number"
placeholder="OT Hours"
/>
<input
value={postData[employee._id].fromDate}
onChange={e =>
updatePostData(employee._id, 'fromDate', e.target.value)
}
type="date"
placeholder="From Date"
/>
<input
value={postData[employee._id].toDate}
onChange={e =>
updatePostData(employee._id, 'toDate', e.target.value)
}
type="date"
placeholder="To Date"
/>
<div>
<AddHoursButton
bordercolor="secondaryColorLight"
type="button"
>
Add Hours
</AddHoursButton>
</div>
</EmployeeTableItem>
))} : null
}
{Object.keys(postData).length!==0?
{employees.map((employeen,i)=>(
{employee.fullName}
updatePostData(employee.\u id,'regHours',e.target.value)
}
type=“编号”
占位符=“注册小时数”
/>
updatePostData(employee.\u id,'otHours',例如target.value)
}
type=“编号”
占位符=“加班时间”
/>
updatePostData(employee.\u id,'fromDate',e.target.value)
}
type=“日期”
占位符=“起始日期”
/>
updatePostData(employee.\u id,'toDate',e.target.value)
}
type=“日期”
占位符=“到目前为止”
/>
增加小时数
))}:null
}
由于我们在组件装载时正在创建postData
对象,因此如果我们初始化输入,它们将无法访问最初装载时在useffect()
中创建的postData
状态。为了避免这种情况,只有在通过三元运算符创建postData
状态后,才会呈现输入。尽管postData
创建得非常快,但在组件最初渲染后仍然会发生轻微的变化,因此输入无法立即访问它
这就是我在这件事上的感受。我相信这可以在某种程度上用一个可重用的钩子实现,但现在这让我进入下一步 谢谢大家!!这非常有帮助。我刚刚开始处理这个问题,updatePostData()
函数的语法无效,即三元表达式。我不确定问题出在哪里,因为我看不到代码,你可以搜索错误或在这里发布代码。我相信你有一个三元运算符导致了这个错误
const updatePostData = (id, key, value) => {
setPostData(prevData => {
return {
...prevData,
[id]: {
...postData[id],
[key]: value
}
};
});
};
{ Object.keys(postData).length !== 0 ?
{employees.map((employee, i) => (
<EmployeeTableItem>
<p>{employee.fullName}</p>
<input
value={postData[employee._id].regHours}
onChange={e =>
updatePostData(employee._id, 'regHours', e.target.value)
}
type="number"
placeholder="Reg. Hours"
/>
<input
value={postData[employee._id].otHours}
onChange={e =>
updatePostData(employee._id, 'otHours', e.target.value)
}
type="number"
placeholder="OT Hours"
/>
<input
value={postData[employee._id].fromDate}
onChange={e =>
updatePostData(employee._id, 'fromDate', e.target.value)
}
type="date"
placeholder="From Date"
/>
<input
value={postData[employee._id].toDate}
onChange={e =>
updatePostData(employee._id, 'toDate', e.target.value)
}
type="date"
placeholder="To Date"
/>
<div>
<AddHoursButton
bordercolor="secondaryColorLight"
type="button"
>
Add Hours
</AddHoursButton>
</div>
</EmployeeTableItem>
))} : null
}