【问题标题】:React Forms - Changing multiple states with multiple event listenersReact Forms - 使用多个事件侦听器更改多个状态
【发布时间】:2022-10-01 07:28:19
【问题描述】:

我正在尝试创建一个 Web 应用程序,该应用程序在用户键入信息时生成简历。

我无法通过 input/handleChange 更改组件状态下对象的属性。我知道我可以通过使用输入的名称作为对我要更改的属性的引用来更改状态对象属性,但是当组件的状态中有多个对象时我不知道如何执行此操作.

我有一个按钮,可以将对象添加到 schoolData 状态并将组件添加到 schoolArray 状态。

输入组件:

import React from \'react\';
import Schools from \'./Schools\';

export default function Input(props) {  
  // school data and event handler
  const [schoolData, setSchoolData] = React.useState(
    [{
      schoolName: \'\', schoolState: \'\', schoolCity: \'\', schoolDegree: \'\', schoolStartDate: \'\', schoolEndDate: \'\', schoolCurrent: false,
    }]
  );

  function handleSchoolChange(event) {
    const { name, value, type, checked } = event.target;
    setSchoolData(prevData => ({
      ...prevData,
      [name]: type === \"checkbox\" ? checked : value
    }));
    console.log(\'school data\', schoolData);
    console.log(\'school data name\', schoolData.name);
    console.log(\'school array\', schoolArray);
  }
  
  // school array and event handler
  const [schoolArray, setSchoolArray] = React.useState([
    <Schools key={schoolData.length} schoolData={schoolData} handleSchoolChange={handleSchoolChange} />,
  ]);

  function addSchool() {
    // add schoolData object
    setSchoolData(prevData => [...prevData, {
      schoolName: \'\', schoolState: \'\', schoolCity: \'\', schoolDegree: \'\', schoolStartDate: \'\', schoolEndDate: \'\', schoolCurrent: false,
    }]);
    
    setSchoolArray(prevSchoolArray => [...prevSchoolArray, <Schools key={schoolData.length + 1} schoolData={schoolData[0]} handleSchoolChange={handleSchoolChange}  />]);
    console.log(schoolArray);
    console.log(schoolElements);
    console.log(\'school name\', schoolData[0].schoolName);
  }

  const schoolElements = schoolArray.map((school, index) => 
    { return school }
  );

  return (
    <form>

      <legend>Education</legend>
      {schoolElements}

    </form>
  )
}

学校组成:

export default function Schools(props) {
  return (
    <div>
      <label htmlFor=\"schoolName\">School Name</label>
      <input
        type=\"text\"
        placeholder=\"School Name\"
        className=\"input\"
        name=\"schoolName\"
        onChange={props.handleSchoolChange}
        value={props.schoolData.schoolName}
      />

      <label htmlFor=\"schoolCity\">City</label>
      <input 
        type=\"text\"
        placeholder=\"City\"
        className=\"input\"
        name=\"schoolCity\"
        onChange={props.handleSchoolChange}
        value={props.schoolData.schoolCity}
      />

      <label htmlFor=\"schoolState\">State</label>
      <input
        type=\"text\"
        placeholder=\"State\"
        className=\"input\"
        name=\"schoolState\"
        onChange={props.handleSchoolChange}
        value={props.schoolData.schoolState}
      />

      <label htmlFor=\"schoolDegree\">Degree</label>
      <input
        type=\"text\"
        placeholder=\"Degree\"
        className=\"input\"
        name=\"schoolDegree\"
        onChange={props.handleSchoolChange}
        value={props.schoolData.schoolDegree}
      />

      <label htmlFor=\"schoolStartDate\">Start Date</label>
      <input 
        type=\"month\"
        placeholder=\"Start Date\"
        className=\"input\"
        name=\"schoolStartDate\"
        onChange={props.handleSchoolChange}
        value={props.schoolData.schoolStartDate}
      />

      <label htmlFor=\"schoolEndDate\">End Date</label>
      <input 
        type=\"month\"
        placeholder=\"End Date\"
        className=\"input\"
        name=\"schoolEndDate\"
        onChange={props.handleSchoolChange}
        value={props.schoolData.schoolEndDate}
      />

      <label htmlFor=\"schoolCurrent\">Still attending</label>
      <input 
        type=\"checkbox\"
        name=\"schoolCurrent\"
        onChange={props.handleSchoolChange}
        checked={props.schoolData.schoolCurrent}
      />
    </div>
  );
}

提前感谢您的帮助!

    标签: reactjs state hook


    【解决方案1】:

    更简单的解决方案是通过输入 onchanges 更新 schoolData 状态变量。这应该让 Input 组件中的 schoolData 保持最新状态。

    学校部分

    export default function Schools(props) {
      return (
        <div>
          <label htmlFor="schoolName">School Name</label>
          <input
            type="text"
            placeholder="School Name"
            className="input"
            name="schoolName"
            onChange={(e) => props.setSchoolData({ ...props.schoolData, schoolName: e.target.value })}
            value={props.schoolData.schoolName}
          />
    
          <label htmlFor="schoolCity">City</label>
          <input 
            type="text"
            placeholder="City"
            className="input"
            name="schoolCity"
             onChange={(e) => props.setSchoolData({ ...props.schoolData, schoolCity: e.target.value })}
            value={props.schoolData.schoolCity}
          />
    
          <label htmlFor="schoolState">State</label>
          <input
            type="text"
            placeholder="State"
            className="input"
            name="schoolState"
             onChange={(e) => props.setSchoolData({ ...props.schoolData, schoolState: e.target.value })}
            value={props.schoolData.schoolState}
          />
    
          <label htmlFor="schoolDegree">Degree</label>
          <input
            type="text"
            placeholder="Degree"
            className="input"
            name="schoolDegree"
             onChange={(e) => props.setSchoolData({ ...props.schoolData, schoolDegree: e.target.value })}
            value={props.schoolData.schoolDegree}
          />
    
          <label htmlFor="schoolStartDate">Start Date</label>
          <input 
            type="month"
            placeholder="Start Date"
            className="input"
            name="schoolStartDate"
             onChange={(e) => props.setSchoolData({ ...props.schoolData, schoolStartDate: e.target.value })}
            value={props.schoolData.schoolStartDate}
          />
    
          <label htmlFor="schoolEndDate">End Date</label>
          <input 
            type="month"
            placeholder="End Date"
            className="input"
            name="schoolEndDate"
             onChange={(e) => props.setSchoolData({ ...props.schoolData, schoolEndDate: e.target.value })}
            value={props.schoolData.schoolEndDate}
          />
    
          <label htmlFor="schoolCurrent">Still attending</label>
          <input 
            type="checkbox"
            name="schoolCurrent"
             onChange={(e) => props.setSchoolData({ ...props.schoolData, schoolCurrent: e.target.value })}
            checked={props.schoolData.schoolCurrent}
          />
        </div>
      );
    }
    

    【讨论】:

      【解决方案2】:

      这里有很多错误。您不应该将组件存储在状态中,您只需要数据。这是非常令人困惑的事情。

      相反,您需要做的是在 render 方法中迭代 schoolData,并为各个学校传递数据本身的适当绑定,以及处理该学校更改的回调。

      import React from 'react';
      import Schools from './Schools';
      
      export default function Input(props) {  
        // school data and event handler
        const [schoolData, setSchoolData] = React.useState(
          [{
            schoolName: '', schoolState: '', schoolCity: '', schoolDegree: '', schoolStartDate: '', schoolEndDate: '', schoolCurrent: false,
          }]
        );
      
        function handleSchoolChange(event, indexToChange) {
          const { name, value, type, checked } = event.target;
          setSchoolData(prevData => {
              return prevData.map((school, index) => index === indexToChange ? {
                 ...prevData[index],
                 [name]: type === "checkbox" ? checked : value
              }) : school
          });
        }
        
      
      
        function addSchool() {
          // add schoolData object
          setSchoolData(prevData => [...prevData, {
            schoolName: '', schoolState: '', schoolCity: '', schoolDegree: '', schoolStartDate: '', schoolEndDate: '', schoolCurrent: false,
          }]);
        
        }
      
        return (
          <form>
      
            <legend>Education</legend>
            {schoolData.map((school, index) => (<School key={index} schoolData={school} handleSchoolChange={(e) => handleSchoolChange(e, index)} />)}
          </form>
        )
      }
      

      【讨论】:

        【解决方案3】:



        我可以建议的一件事是在您的 Input 组件中,有一个对象变量和一个对象数组变量,使用单个对象填充信息,填充信息后将其添加到对象数组中,然后将对象数组作为道具传递给学校。然后在 School 组件中,如果数组为空,您可以返回映射的数组或其他内容。

        function Input(props) {
        const [schoolData, setSchoolData] = useState({ single object })
        const [schoolsArray, setSchoolsArray] = useState([{},...])
        
        // use setSchoolData to fill out schoolData Variable
        
        const handleAddingSchool = () => {
            setSchoolsArray([...schoolsArray, schoolData])
        }
        
        
        return (
        <>
            <School schoolArray={schoolsArray}/>
        <>
        )
        }
        
        // New Basic School Component Layout
        function School (props) {
            return {
            <>
                {
                    props.schoolArray.length > 0 
                    ? <SchoolComponentStuff....>
                    : <NothingToSeeHere....>
                }
            <>
            }
        }
        

        您将必须填写您的关键部分,但我认为这将解决您的问题。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-02-26
          • 2020-05-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多