Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/apache/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 反应-如何管理多个动态创建的受控输入的状态?_Javascript_Reactjs - Fatal编程技术网

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 
}