[英]How to stop State object from updating with onChange of an input field in React js
I am trying to create a multi step register form for my app.我正在尝试为我的应用程序创建一个多步骤注册表单。 I am saving form data to a "registerData" state.
我正在将表单数据保存到“registerData”state。
I have a problem with inputting data.我在输入数据时遇到问题。 Whenever I try to input data in one of the component pages (for example page1, Name), it does the onChange and changes the Name from "" to inputted letter but immediately after that it reverts "registerData" to its original state with all properties set to "".
每当我尝试在其中一个组件页面(例如 page1,Name)中输入数据时,它都会执行 onChange 并将名称从“”更改为输入的字母,但之后它会立即将“registerData”恢复为具有所有属性的原始 state调成 ””。
Here is the code:这是代码:
Register.js:注册.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 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>
)
}
As I don't have much experience with react, it's hard for me to tell but I think the problem lays in the Register.js rerendering with each change to the "registerData" state which causes it to revert to its original values.由于我没有太多的反应经验,所以我很难说,但我认为问题出在 Register.js 每次更改“registerData”state 时都会重新呈现,这会导致它恢复为原始值。
Try this as a function for onChange values... It helps you a lot.试试这个作为 onChange 值的 function ...它对你有很大帮助。 Secondly, in you input tag add the name attribute with the same state object names.
其次,在您输入的标签中添加具有相同 state object 名称的名称属性。
For Example:例如:
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>
You shouldn't store JSX in state. Your pages
state isn't a state value, as it can be calculated by other state values in this case ( pageIndex
).您不应该将 JSX 存储在 state 中。您的
pages
state 不是 state 值,因为在这种情况下它可以由其他 state 值计算( pageIndex
)。 Another thing that hints that it shouldn't be a state value is that you're never using setPages()
.暗示它不应该是 state 值的另一件事是您从不使用
setPages()
。 Instead, you can make this a regular object:相反,您可以将其设为常规 object:
const pages = [
<Page1 registerData={registerData} setRegisterData={(data) => {setRegisterData(data)}} />,
<Page2 registerData={registerData} setRegisterData={(data) => {setRegisterData(data)}} />,
<Page3 registerData={registerData} setRegisterData={(data) => {setRegisterData(data)}} />
];
I would also consider putting the above into its own component called Page
which accepts a page number as an index and then uses that number in a simple if-statement to decide which page component ( Page1
, Page2
, Page3
) to render.我还会考虑将上面的内容放入它自己的名为
Page
的组件中,该组件接受页码作为索引,然后在简单的 if 语句中使用该页码来决定要呈现哪个页面组件( Page1
、 Page2
、 Page3
)。
So, why does making pages
a regular object instead of a state value fix this issue?那么,为什么将
pages
设置为常规 object 而不是 state 值可以解决此问题? Each time your Register
component rerenders, the code within Register
runs, causing the line with useState()
to execute again:每次您的
Register
组件重新呈现时, Register
中的代码都会运行,导致带有useState()
的行再次执行:
const [pages, setPages] = useState(/* initival value */ [...])
The "initial value" argument that you pass to useState()
is ignored after the initial render, so while the "initial value" gets evaluated each time your component rerenders, it gets ignored and the value of pages
doesn't change, only using setPages()
can change pages
.您传递给
useState()
的“初始值”参数在初始渲染后会被忽略,因此当每次组件重新渲染时“初始值”都会被评估,它会被忽略并且pages
的值不会改变,仅使用setPages()
可以改变pages
。 This results in pages
storing an array of object references that represent your JSX on the initial mount of your component.这会导致
pages
存储一个 object 引用数组,这些引用代表组件初始挂载时的 JSX。 That means that on subsequent rerenders of your component, pages[pageIndex]
will always return the same JSX object reference, and as it's the same on every rerender, React won't rerender this component.这意味着在组件的后续重新渲染中,
pages[pageIndex]
将始终返回相同的 JSX object 引用,并且在每次重新渲染时都是相同的,React 不会重新渲染该组件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.