You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React多步骤注册表单:输入框onChange后State被重置的解决方法

问题描述

开发多步骤注册表单时,将表单数据存储在registerData状态中,但输入内容时(例如Page1的姓名输入框),onChange会短暂更新对应字段,随后registerData立刻恢复为所有属性为空的初始状态。

相关代码

Register.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>
  )
}

问题原因

  • 你把页面组件实例存在了pages这个useState中,初始渲染时这些组件拿到的是registerData的初始值。当registerData更新触发Register组件重渲染时,pages状态并未更新,依然保存着旧的组件实例,这些旧实例使用的还是初始的registerData,导致显示内容回退。
  • Page1中生日输入框的value绑定错误,写成了registerData.Date,但状态中对应的字段是Birthday,会导致输入的生日无法正确显示。

修复方案

1. 移除存储页面组件的pages状态,动态渲染页面组件

不需要把页面组件存在state里,每次渲染时根据pageIndex直接渲染对应组件,保证组件拿到最新的registerData和setRegisterData。

2. 修正Page1中生日输入框的value绑定

将value={registerData.Date}改为value={registerData.Birthday}。

修改后的代码

调整后的Register.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: "",
      Birthday: "",
      //Address
      Street: "",
      Zip: "",
      Building: "",
      House: "",
      City: "",
      Voivodeship: "",
      //Login information
      Email: "",
      Password: ""
    }
  ) 

  const [ pageIndex, setPageIndex] = useState(0)

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

  const HandleSubmit = (event) => {
    event.preventDefault();
    if (pageIndex !== 2){ // 总共有3个页面,索引为0、1、2
      setPageIndex(pageIndex + 1)
      return
    }

    console.log("Submmited", registerData)
  }

  // 根据当前页码渲染对应页面
  const renderCurrentPage = () => {
    switch(pageIndex) {
      case 0:
        return <Page1 registerData={registerData} setRegisterData={setRegisterData}/>
      case 1:
        return <Page2 registerData={registerData} setRegisterData={setRegisterData}/>
      case 2:
        return <Page3 registerData={registerData} setRegisterData={setRegisterData}/>
      default:
        return null
    }
  }

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

      <form className='register-form' onSubmit={HandleSubmit}>
        {renderCurrentPage()}
        {pageIndex !== 0 && <button type="button" onClick={PrevPage}>Poprzedni</button>}
        <button type="submit">{pageIndex !== 2? "Nastepny" : "Przeslij"}</button>
      </form>

    </div>
  );
}

export default Register;

调整后的Page1.js

import React from 'react'

export default function Page1({registerData, setRegisterData}) {
  return (
    <div>
        <input
            placeholder='Imie'
            required type='text'
            value={registerData.Name}
            onChange={(e) => { setRegisterData({...registerData, Name: 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.Birthday}
                onChange={e => { setRegisterData({...registerData, Birthday: e.target.value}) }}
            />
        </div>
    </div>
  )
}

内容的提问来源于stack exchange,提问作者MaciejT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 05:45:35