繁体   English   中英

如何阻止 State object 在 React js 中更新输入字段的 onChange

[英]How to stop State object from updating with onChange of an input field in React js

我正在尝试为我的应用程序创建一个多步骤注册表单。 我正在将表单数据保存到“registerData”state。

我在输入数据时遇到问题。 每当我尝试在其中一个组件页面(例如 page1,Name)中输入数据时,它都会执行 onChange 并将名称从“”更改为输入的字母,但之后它会立即将“registerData”恢复为具有所有属性的原始 state调成 ””。

这是代码:

注册.js:

import React, {useState} from 'react';
import Page1 from './register_components/Page1';
import Page2 from './register_components/Page2';
import Page3 from './register_components/Page3';

function Register() {
  const [registerData, setRegisterData] = useState(
    {
      //Personal Details
      Name: "",
      LastName: "",
      Phone: "", //Null
      Birthday: "", //Null
      //Address
      Street: "",
      Zip: "",
      Building: "",
      House: "", //Null
      City: "",
      Voivodeship: "",
      //Login information
      Email: "",
      Password: ""
    }
  ) 


  const [ pageIndex, setPageIndex] = useState(0)
  const [ pages, setPages ] = useState([
    <Page1 registerData={registerData} setRegisterData={(data) => {setRegisterData(data)}}/>,
    <Page2 registerData={registerData} setRegisterData={(data) => {setRegisterData(data)}}/>,
    <Page3 registerData={registerData} setRegisterData={(data) => {setRegisterData(data)}}/>
  ])

  const PrevPage = () =>{
    if (pageIndex <= 0)
      return
    setPageIndex(pageIndex - 1)
  }

  const HandleSubmit = (event) => {
    event.preventDefault();
    if (pageIndex !== pages.length - 1){
      setPageIndex(pageIndex + 1)
      return
    }

    console.log("Submmited")
  }

  return (
    <div className="App">
      <h1>Rejestracja</h1>

      <form className='register-form' onSubmit={HandleSubmit}>
        {pages[pageIndex]}
        {pageIndex !== 0 && <button type="button" onClick={ () => {PrevPage()}}>Poprzedni</button>}
        <button type="submit">{pageIndex !== pages.length - 1? "Nastepny" : "Przeslij"}</button>
      </form>

    </div>
  );
}


export default Register;

Page1.js

import React from 'react'

export default function Page1({registerData, setRegisterData}) {
    console.log("rerender")
    console.log(registerData)
  return (
    <div>
        <input
            placeholder='Imie'
            required type='text'
            value={registerData.Name}
            onChange={(e) => { setRegisterData({...registerData, Name: e.target.value}); console.log(e.target.value) }}
        />
        
        <input
            placeholder='Nazwisko'
            required
            type='text'
            value={registerData.LastName}
            onChange={(e) => { setRegisterData({...registerData, LastName: e.target.value}) }}
        />
        
        <input
            placeholder='Nr telefonu'
            required
            type='text'
            value={registerData.Phone}
            onChange={(e) => { setRegisterData({...registerData, Phone: e.target.value}) }}
        />
        
        <div className='date-form'>
            <label>Data urodzenia</label>
            <input
                type='date'
                value={registerData.Date}
                onChange={e => { setRegisterData({...registerData, Birthday: e.target.value}) }}
            />
        </div>
    </div>
  )
}

由于我没有太多的反应经验,所以我很难说,但我认为问题出在 Register.js 每次更改“registerData”state 时都会重新呈现,这会导致它恢复为原始值。

试试这个作为 onChange 值的 function ...它对你有很大帮助。 其次,在您输入的标签中添加具有相同 state object 名称的名称属性。

例如:

    const [registerData, setRegisterData] = useState(
{
    //Personal Details
    Name: "",
    LastName: "",
    Phone: "", //Null
    Birthday: "", //Null
    //Address
    Street: "",
    Zip: "",
    Building: "",
    House: "", //Null
    City: "",
    Voivodeship: "",
    //Login information
     Email: "",
     Password: ""
   }
 ) 


  const handleFormChange = (index, event) => {
   let data = [...inputFields];
   data[index][event.target.name] = event.target.value;
   setInputFields(data);
 };

<div>
      <input
          placeholder='Imie'
          required type='text'
          name="Name"
          value={registerData.Name}
          onChange={(event) => handleFormChange(index, event)}
      />
    
    <input
        placeholder='Nazwisko'
        required
        type='text'
            name="LastName"
            value={registerData.LastName}
           onChange={(event) => handleFormChange(index, event)}
      />
    
   
      </div>
  </div>

您不应该将 JSX 存储在 state 中。您的pages state 不是 state 值,因为在这种情况下它可以由其他 state 值计算( pageIndex )。 暗示它不应该是 state 值的另一件事是您从不使用setPages() 相反,您可以将其设为常规 object:

const pages = [
  <Page1 registerData={registerData} setRegisterData={(data) => {setRegisterData(data)}} />,
  <Page2 registerData={registerData} setRegisterData={(data) => {setRegisterData(data)}} />,
  <Page3 registerData={registerData} setRegisterData={(data) => {setRegisterData(data)}} />
];

我还会考虑将上面的内容放入它自己的名为Page的组件中,该组件接受页码作为索引,然后在简单的 if 语句中使用该页码来决定要呈现哪个页面组件( Page1Page2Page3 )。

那么,为什么将pages设置为常规 object 而不是 state 值可以解决此问题? 每次您的Register组件重新呈现时, Register中的代码都会运行,导致带有useState()的行再次执行:

const [pages, setPages] = useState(/* initival value */ [...])

您传递给useState()的“初始值”参数在初始渲染后会被忽略,因此当每次组件重新渲染时“初始值”都会被评估,它会被忽略并且pages的值不会改变,仅使用setPages()可以改变pages 这会导致pages存储一个 object 引用数组,这些引用代表组件初始挂载时的 JSX。 这意味着在组件的后续重新渲染中, pages[pageIndex]将始终返回相同的 JSX object 引用,并且在每次重新渲染时都是相同的,React 不会重新渲染该组件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM