簡體   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