[英]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 語句中使用該頁碼來決定要呈現哪個頁面組件( Page1
、 Page2
、 Page3
)。
那么,為什么將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.