在材质ui TextField中动态反应输入值的更改数组

时间:2020-11-03 11:51:28

标签: javascript arrays reactjs input material-ui

我正在尝试在一系列可用项目中更改项目名称的input value:-

// lets say i've projects like so
const projects = [
  { _id: 1, name: 'Project 1' },
  { _id: 2, name: 'Project 2' },
  { _id: 3, name: 'Project 3' }
]

const Projects = () = {
  // declaration of state
  const [projectName, setProjectName] = useState('')
  const [projectId, setProjectId] = useState('')
  const [isSubmit, setIsSubmit] = useState(false) 

  // handle submission of updated input
  useEffect(() => {
    (async() => {
      if(isSubmit) {
        // do fetch post submission to server

        // reset everything back
        setProjectName('')
        setIsSubmit(false)
      }
    })();
  }, [isSubmit])

  return (
    <>
      <table>
        <thead>
          <tr>
            <th>Name</th>
            <th>Submission</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            {projects && projects.map(project => (
              <form 
                key={project._id}
                onSubmit={(e) => {
                  e.preventDefault()
                  setProjectId(project._id)
                  setIsSubmit(true)
                }}
              >
                <td>
                  <TextField
                    required
                    label="Name" 
                    value={project.name} 
                    onChange={(e) => setProjectName(e.target.value)}    
                  />
                </td>
                <td>
                  <Button type="submit">Update</Button>
                </td>
              </form>
             ))}
           </tr>
         </tbody>
       </table>
     </>
  )
}

不幸的是,由于value={project.name}onChange事件在这种情况下基本上将根本无法工作。 顺便说一句,这还将引入新的问题,即以下数组的所有input TextField也将被更新。

如何使用React实现这一目标?使用Vanilla JavaScript进行操作要简单得多。不知道如何用React tho做到这一点。还是不建议这样做?相反,我应该创建一个Modal还是可以单独处理项目名称更改的内容?

我的目标是从表本身启用直接更新。

1 个答案:

答案 0 :(得分:0)

所以,关于第一个问题:

由于value = {project.name},因此onChange事件基本上将根本无法工作

那是因为您的onChange使用了setProjectName,并且被绑定到projectName变量上(由于useState的原因)。

如果您使用value={projectName},则onChange可以使用,但不会执行您想要的操作。

要实现这一点,就是让React状态管理所有项目数组:

// Your initial data.
const projectsDefault = [
  { _id: 1, name: 'Project 1' },
  { _id: 2, name: 'Project 2' },
  { _id: 3, name: 'Project 3' }
]

const Projects = () => {
  // The only needed state to manage projects
  const [projects, setProjects] = useState(projectsDefault)
  
  const [projectId, setProjectId] = useState('')
  const [isSubmit, setIsSubmit] = useState(false)
  
  // You can write it on the "onChange" event, but it's better to have a handle function.
  // Also, i'm using the index, but you can use the ID, it's just a example.
  const handleNameChange = (name, index) => {
      // You can use a functional setState, so you get the old value and do some updates on it, and return the new state.
      setProjects(oldState => {
          oldState[index].name = name
          return oldState
      })
  }

  // handle submission of updated input
  useEffect(() => {
    (async() => {
      if(isSubmit) {
        // do fetch post submission to server

        setIsSubmit(false)
      }
    })();
  }, [isSubmit])

  return (
    <>
      <table>
        <thead>
          <tr>
            <th>Name</th>
            <th>Submission</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            {projects && projects.map((project, index) => (
              <form 
                key={project._id}
                onSubmit={(e) => {
                  e.preventDefault()
                  setProjectId(project._id)
                  setIsSubmit(true)
                }}
              >
                <td>
                  <TextField
                    required
                    label="Name" 
                    value={project.name} 
                    onChange={(e) => handleNameChange(e.target.value, index)}    
                  />
                </td>
                <td>
                  <Button type="submit">Update</Button>
                </td>
              </form>
             ))}
           </tr>
         </tbody>
       </table>
     </>
  )
}