渲染文本输入后使用useState Hook更新对象

时间:2019-07-18 05:30:27

标签: javascript reactjs object setstate

我正在为我们的公司构建调试清单应用程序的早期阶段。由于清单很大(其中许多清单),因此我想创建一个映射到对象的函数,并且在渲染所编写的值之后,将使用useState Hook更新相应的状态。

页面正在呈现,没有任何问题。仅在更改输入后才出现问题。而不是更新对象中的正确状态。看来逻辑是在对象中添加了一个附加部分并创建了另一个输入元素。

import React, { useState } from 'react'


const ProjectInfo = () => {

  const _renderObject= () => {
     return Object.keys(answers).map((obj, i) => {
        return(
            <div key={obj}>
                <label>{answers[obj].question}</label>
                <input type="text" onChange={(e, obj) => setAnswer(
                    {
                    ...answers,
                    obj:{
                       value: e.target.value
                    }})} />    
            </div>
        )
    })
}

const [answers, setAnswer] = useState({
    11:{
        question:"Project Name",
        value:""
    },
    12:{
        question:"Project Number",
        value:"" 
    }
})

    return(
        <div>
            <section>
                {_renderObject()}
            </section>
            <p>{`Project Number is: ${answers[11].value}`}</p>
            <p>{`Project Name is: ${answers[12].value}`}</p>
        </div>
    )
}

export default ProjectInfo

我期望状态会正常更新。但是我怀疑我的renderObject方法中的.map函数的obj变量未在setAnswer函数中使用,并导致另一个字段的键名为“ obj”。

如果这是问题所在,是否有可能在我的renderObject方法中使用setAnswer函数来使用map函数的“ obj”值,而不是将obj这个词的实际值用作键?

如果不是,最好的方法是什么?我正在考虑在屏幕底部添加一个提交按钮,并使用onClick事件侦听器更新所有状态。但是现在我想我会遇到同样的问题,因为obj变量的范围没有解决。

任何帮助将不胜感激。我只做了几个月,任何建议和反馈也将不胜感激!

3 个答案:

答案 0 :(得分:3)

您似乎在更新状态时未正确使用动态键。另外,您需要更新键中的值,而不要覆盖它。此外,obj不应是onChange的第二个参数,而必须从封闭范围接收

const _renderObject= () => {
     return Object.keys(answers).map((obj, i) => {
        return(
            <div key={obj}>
                <label>{answers[obj].question}</label>
                <input type="text" onChange={(e) => setAnswer(
                    {
                    ...answers,
                   [obj]:{
                       ...answers[obj],
                       value: e.target.value
                    }})} />    
            </div>
        )
    })

答案 1 :(得分:0)

onChange={(e, obj) => setAnswer(
                    {
                    ...answers,
                    obj:{
                       value: e.target.value
                    }})}

在这里您分发答案并添加具有目标值的另一个对象。这就是问题。希望你理解这一点。

请尝试

onChange={
  (e, obj) => {
    const updatedAnswer = answer.map(ans => ans.question === obj.question ? {...ans,value: e.target.value }:ans)
    setAnswer(
      {
        ...updatedAnswer
      }
    )
  }
} 

您的对象应包含该密钥的属性ID。

答案 2 :(得分:0)

这是因为您没有正确更新键,并且需要在输入onchange回调中传递obj,因为它会提供另一个引用,而不是映射的array(obj)。因此,在您的情况下obj是未定义的。这是工作代码:

const _renderObject = () => {
    return Object.keys(answers).map((obj, i) => {
      return (
        <div key={obj}>
          <label>{answers[obj].question}</label>
          <input
            type="text"
            onChange={e =>

              setAnswer({
                ...answers,
                [obj]: {   //take obj
                  ...answers[obj],//keep specific object question
                  value: e.target.value//change only specfic object value
                }
              })
            }

          />
        </div>
      );
    });
  };

这是有效的网址:https://codesandbox.io/s/hardcore-pike-s2hfx