[英]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.