You need to enable JavaScript to run this app. Next.js多步骤表单使用React Context修改Stepper步骤状态问题
优惠活动
大模型
产品
解决方案
定价
更多

Next.js多步骤表单使用React Context修改Stepper步骤状态问题

核心问题说明

  1. 你的FormContext仅提供了steps状态的读取权限,没有对外暴露修改steps的方法,外部无法更新步进器状态
  2. index.js中重复定义了formStep和activeStep两个功能完全一致的状态,没有和Context中的steps做联动
  3. index.js中没有引入FormContext,直接操作step变量自然会报未定义错误

修改方案

步骤1:更新Context文件,新增steps状态修改方法

在FormProvider中新增专门的状态更新方法,根据传入的激活步骤索引批量更新所有step的status,再将该方法暴露到Context中:

// context/FormContext.js
import { useState, createContext, useContext } from "react";

export const FormContext = createContext();

export default function FormProvider({ children }) {
  const [data, setData] = useState({});
  const [steps, setSteps] = useState([
    { name: 'Vertrag', status: 'current' },
    { name: 'Dateneingabe', status: 'upcoming' },
    { name: 'Bestätigung', status: 'upcoming' },
  ]);

  const setFormValues = (values) => {
    setData((prevValues) => ({
      ...prevValues,
      ...values,
    }));
  };

  // 新增:根据当前激活索引更新所有步骤的status
  const updateStepsStatus = (activeIndex) => {
    const newSteps = steps.map((step, idx) => {
      if (idx < activeIndex) return { ...step, status: 'complete' }
      if (idx === activeIndex) return { ...step, status: 'current' }
      return { ...step, status: 'upcoming' }
    })
    setSteps(newSteps)
  }

  return (
    <FormContext.Provider value={{ steps, data, setFormValues, updateStepsStatus }}>
      {children}
    </FormContext.Provider>
  );
}

export const useFormData = () => useContext(FormContext);

步骤2:修改index.js,联动步骤切换逻辑

删掉重复的activeStep状态,直接用formStep作为激活索引,每次切换步骤时调用Context中的更新方法同步步进器状态:

// pages/index.js
import { useState } from "react";
import Head from "next/head";
import Stepper from '../components/Stepper'
import styles from "../styles/styles.module.scss";
import FormCard from "../components/FormCard";
import Navbar from "../components/Navbar";
import { useFormData } from "../context/FormContext"; // 引入Context Hook

import {
  PersonalInfo,
  ConfirmPurchase,
  ContractInfo,
} from "../components/Forms";

import FormCompleted from "../components/FormCompleted";

function classNames(...classes) {
  return classes.filter(Boolean).join(' ')
}

const App = () => {
  const { updateStepsStatus } = useFormData(); // 拿到步进器更新方法
  const [formStep, setFormStep] = useState(0);

  const nextFormStep = () => {
    const newStep = formStep + 1
    setFormStep(newStep);
    updateStepsStatus(newStep); // 切换步骤时同步更新步进器状态
  };
  const prevFormStep = () => {
    const newStep = formStep - 1
    setFormStep(newStep);
    updateStepsStatus(newStep); // 切换步骤时同步更新步进器状态
  };

  return (
    <div>
      <Head>
        <title>Next.js Multi Step Form</title>
      </Head>
      <Navbar />
      <Stepper /> {/* 删掉多余的activeStep传参 */}
        <div className={styles.container}>
          <FormCard currentStep={formStep} prevFormStep={prevFormStep}>
            {formStep >= 0 && (
              <ContractInfo formStep={formStep} nextFormStep={nextFormStep} />
            )}
            {formStep >= 1 && (
              <PersonalInfo formStep={formStep} nextFormStep={nextFormStep} />
            )}
            {formStep >= 2 && (
              <ConfirmPurchase formStep={formStep} nextFormStep={nextFormStep} />
            )}
            {formStep > 2 && <FormCompleted />}
          </FormCard>
        </div>
        <div className="mt-1 mb-5 sm:mt-8 sm:flex sm:justify-center lg:justify-center">
          <div className="rounded-md shadow">
            <a role="button" tabIndex={0}
            onClick={prevFormStep}
            className="w-full flex items-center justify-center px-8 py-3 border border-transparent text-base font-medium rounded-md text-white bg-yellow-500 hover:bg-yallow-600 md:py-4 md:text-lg md:px-10"
            >
              Back
            </a>
          </div>
          <div className="mt-3 sm:mt-0 sm:ml-3">
            <a
              onClick={nextFormStep}
              className="w-full flex items-center justify-center px-8 py-3 border border-transparent text-base font-medium rounded-md text-white bg-yellow-500 hover:bg-yallow-600 md:py-4 md:text-lg md:px-10"
            >
              Next
            </a>
          </div>
      </div>
    </div>
  );
};

export default App;

步骤3:确认全局包裹FormProvider

确保你的项目根组件(一般是pages/_app.js)已经用FormProvider包裹了所有页面组件,这样Context才能正常工作:

// pages/_app.js
import FormProvider from '../context/FormContext'

export default function MyApp({ Component, pageProps }) {
  return (
    <FormProvider>
      <Component {...pageProps} />
    </FormProvider>
  )
}

你现有的Stepper组件逻辑不需要修改,Context中的steps更新后会自动触发Stepper重新渲染,样式会同步更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.09 05:27:02