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

提交子表单后重新渲染父组件以重置bs-stepper向导

解决bs-stepper表单提交后重置向导的问题

我使用bs-stepper实现长表单向导,表单数据存储在父组件state中。提交表单后,虽然已将父组件state重置为初始值,但向导仍停留在最后一步,输入框旧内容也未清空。需要实现提交后将向导重置回第一步,同时清空所有输入内容。

原父组件代码:

import Step1 from './step1'
import Step2 from './step2'
import StepLast from './steplast'

const Parent = () => {
  const initialState = {
    name: '',
    lastname: '',
    email: '',
    // and so on
  }

  const [data, setData] = useState(initialState)

  const steps = [
    { id: 'step1', title: 'Step One', content: <Step1 data={data}, setData={setData} />},
    { id: 'step2', title: 'Step Two', content: <Step2 data={data}, setData={setData} />},
    { id: 'steplast', title: 'Step Last', content: <StepLast data={data}, setData={setData} initialState={initialState} />}
  ]
  
  return (
    <>
     <Wizard steps={steps} />
    </>
  )
}

export default Parent

原Step1组件:

const Step1 = ({data, setData}) => {
  const nextStep = (e) => {
    e.preventDefault()
    // go to next step
  }

  return (
    <>
      <Form>
        <Input type='text' onInput={e => setData({...data, name: e.target.value})} />
        <Button type='button' onClick={e => nextStep(e)} />
      </Form>
    </>
  )
}

原StepLast组件:

const StepLast = ({data, setData, initialState}) => {
  const saveData = () => {
    axios.post('api/address', data)
    .then(response => {
      console.log(response) // this is ok

      setData(initialState) // this is resetting state

      // HERE I NEED TO RESTART THE WIZARD
      
    })
    .catch(error => {
      console.error('error', error)
    }

  }

  return (
    <>
      <Form onSubmit={handleSubmit(saveData)}>
        <Input type='email' onInput={e => setData({...data, email: e.target.value})} />
        <Button type='submit' />
      </Form>
    </>
  )
}

解决方案

1. 父组件新增状态控制与重置逻辑

在父组件中添加当前步骤跟踪状态、stepper实例引用,并定义重置方法传递给子组件:

import Step1 from './step1'
import Step2 from './step2'
import StepLast from './steplast'
import { useState, useRef } from 'react'

const Parent = () => {
  const initialState = {
    name: '',
    lastname: '',
    email: '',
    // 其他字段
  }

  const [data, setData] = useState(initialState)
  const [currentStep, setCurrentStep] = useState(1) // 跟踪当前步骤
  const stepperRef = useRef(null) // 获取bs-stepper实例

  // 重置向导与表单数据
  const resetStepper = () => {
    setData(initialState)
    setCurrentStep(1)
    // 调用bs-stepper实例方法跳转到第一步
    if (stepperRef.current) {
      stepperRef.current.to(1)
    }
  }

  const steps = [
    { 
      id: 'step1', 
      title: 'Step One', 
      content: <Step1 
                key={`step1-${data.name}`} // 动态key确保data变化时重新渲染组件
                data={data} 
                setData={setData} 
                setCurrentStep={setCurrentStep} 
              />
    },
    { 
      id: 'step2', 
      title: 'Step Two', 
      content: <Step2 
                key={`step2-${data.lastname}`}
                data={data} 
                setData={setData} 
                setCurrentStep={setCurrentStep} 
              />
    },
    { 
      id: 'steplast', 
      title: 'Step Last', 
      content: <StepLast 
                key={`steplast-${data.email}`}
                data={data} 
                setData={setData} 
                resetStepper={resetStepper} // 传递重置方法
              />
    }
  ]
  
  return (
    <>
     <Wizard ref={stepperRef} steps={steps} currentStep={currentStep} />
    </>
  )
}

export default Parent

2. 调整StepLast组件调用重置方法

提交成功后直接调用父组件的重置方法:

import axios from 'axios'
import { handleSubmit } from 'react-hook-form'

const StepLast = ({data, setData, resetStepper}) => {
  const saveData = () => {
    axios.post('api/address', data)
    .then(response => {
      console.log(response)
      resetStepper() // 触发重置
    })
    .catch(error => {
      console.error('error', error)
    })
  }

  return (
    <>
      <Form onSubmit={handleSubmit(saveData)}>
        <Input 
          type='email' 
          value={data.email} // 绑定value确保与state同步
          onInput={e => setData({...data, email: e.target.value})} 
        />
        <Button type='submit' />
      </Form>
    </>
  )
}

3. 完善步骤组件的输入框绑定

给所有步骤的输入框添加value属性,确保state变化时输入框内容同步更新:

const Step1 = ({data, setData, setCurrentStep}) => {
  const nextStep = (e) => {
    e.preventDefault()
    setCurrentStep(2) // 更新步骤
  }

  return (
    <>
      <Form>
        <Input 
          type='text' 
          value={data.name} // 绑定value
          onInput={e => setData({...data, name: e.target.value})} 
        />
        <Button type='button' onClick={nextStep} />
      </Form>
    </>
  )
}

核心要点

  • 绑定value属性:这是输入框内容与state同步的关键,之前的代码缺少此绑定导致state重置后输入框未更新。
  • 控制步骤状态:通过父组件的currentStep管理向导进度,提交后重置为第一步。
  • 操作stepper实例:利用ref调用bs-stepper的to()方法,强制向导UI跳转到第一步。
  • 动态key:给步骤组件添加基于data的动态key,确保data重置时组件重新挂载,彻底清空输入内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 02:26:19