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

基于React与Material-UI的Web表单确认页面实现咨询

How to Implement the Confirmation Page for Your React + Material-UI Form

Got it, let's fix this confirmation page issue. The core problem here is that you're not storing the user's input anywhere—so when you get to step 3, there's no data to display. Here's a complete, step-by-step solution:

1. Add State to Track Form Data

First, we need a state object in your Content component to store all user inputs across every step. Initialize it with default values matching each field in your form.

2. Bind Inputs to Update State

Modify each form component (RadioGroups, Selects, TextField) to update the state whenever the user makes a selection or types. We'll use onChange handlers for this.

3. Render Saved Data in the Confirmation Step

Update the case 3 section of getStepContent to display the values stored in state instead of just labels, converting raw values to human-readable text where needed.

Modified Content.js Code

import React from "react";
import { Grid } from "@mui/material";
import Stepper from "@mui/material/Stepper";
import Step from "@mui/material/Step";
import StepLabel from "@mui/material/StepLabel";
import Button from "@mui/material/Button";
import Typography from "@mui/material/Typography";
import Radio from "@mui/material/Radio";
import RadioGroup from "@mui/material/RadioGroup";
import FormControlLabel from "@mui/material/FormControlLabel";
import FormControl from "@mui/material/FormControl";
import FormLabel from "@mui/material/FormLabel";
import Tooltip from "@mui/material/Tooltip";
import TextField from "@mui/material/TextField";
import InputLabel from "@mui/material/InputLabel";
import Select from "@mui/material/Select";

function getSteps() {
  return ["请填写客户信息", "请回答以下问题", "请填写咨询内容", "请确认以下内容"];
}

function getStepContent(stepIndex, formContext) { // Pass state and setter as context
  const { formData, setFormData } = formContext;
  switch (stepIndex) {
    case 0:
      return (
        <>
          <div>
            <FormControl component="fieldset">
              <FormLabel component="legend">- 性别 -</FormLabel>
              <RadioGroup 
                row 
                aria-label="gender" 
                name="row-radio-buttons-group"
                value={formData.gender || ""}
                onChange={(e) => setFormData(prev => ({...prev, gender: e.target.value}))}
              >
                <FormControlLabel value="male" control={<Radio />} label="男" />
                <FormControlLabel value="female" control={<Radio />} label="女" />
              </RadioGroup>
            </FormControl>
          </div>
          <div>
            <FormLabel component="legend">- 出生日期 -</FormLabel>
            <FormControl sx={{ m: 1, minWidth: 120 }}>
              <InputLabel htmlFor="birth-year">year</InputLabel>
              <Select 
                native 
                defaultValue="" 
                id="birth-year" 
                label="Grouping"
                value={formData.birthYear || ""}
                onChange={(e) => setFormData(prev => ({...prev, birthYear: e.target.value}))}
              >
                <option aria-label="None" value="" />
                <optgroup label="year">
                  {Array.from(Array(2020), (_, num) => (
                    <option key={num} value={num + 1}>
                      {num + 1990}
                    </option>
                  ))}
                </optgroup>
              </Select>
            </FormControl>
            <FormControl sx={{ m: 1, minWidth: 120 }}>
              <InputLabel htmlFor="birth-month">month</InputLabel>
              <Select 
                native 
                defaultValue="" 
                id="birth-month" 
                label="Grouping"
                value={formData.birthMonth || ""}
                onChange={(e) => setFormData(prev => ({...prev, birthMonth: e.target.value}))}
              >
                <option aria-label="None" value="" />
                <optgroup label="month">
                  {Array.from(Array(12), (_, num) => (
                    <option key={num} value={num + 1}>
                      {num + 1}
                    </option>
                  ))}
                </optgroup>
              </Select>
            </FormControl>
            <FormControl sx={{ m: 1, minWidth: 120 }}>
              <InputLabel htmlFor="birth-day">day</InputLabel>
              <Select 
                native 
                defaultValue="" 
                id="birth-day" 
                label="Grouping"
                value={formData.birthDay || ""}
                onChange={(e) => setFormData(prev => ({...prev, birthDay: e.target.value}))}
              >
                <option aria-label="None" value="" />
                <optgroup label="day">
                  {Array.from(Array(31), (_, num) => (
                    <option key={num} value={num + 1}>
                      {num + 1}
                    </option>
                  ))}
                </optgroup>
              </Select>
            </FormControl>
          </div>
        </>
      );
    case 1:
      return (
        <div>
          <FormControl component="fieldset">
            <FormLabel component="legend">您目前是否已加入人寿保险?</FormLabel>
            <RadioGroup 
              row 
              aria-label="hasInsurance" 
              name="hasInsurance"
              value={formData.hasInsurance || ""}
              onChange={(e) => setFormData(prev => ({...prev, hasInsurance: e.target.value}))}
            >
              <FormControlLabel value="yes" control={<Radio />} label="是" />
              <FormControlLabel value="no" control={<Radio />} label="否" />
            </RadioGroup>
            <FormLabel component="legend">
              您目前是否正在住院?或者在3个月内,是否有过经医师诊断/检查后被建议住院或手术的情况?
            </FormLabel>
            <RadioGroup 
              row 
              aria-label="isHospitalized" 
              name="isHospitalized"
              value={formData.isHospitalized || ""}
              onChange={(e) => setFormData(prev => ({...prev, isHospitalized: e.target.value}))}
            >
              <FormControlLabel value="yes" control={<Radio />} label="是" />
              <FormControlLabel value="no" control={<Radio />} label="否" />
            </RadioGroup>
            <FormLabel component="legend">
              过去5年内,您是否因疾病或受伤接受过手术,或有过连续7天以上的住院经历?
            </FormLabel>
            <RadioGroup 
              row 
              aria-label="hadSurgery" 
              name="hadSurgery"
              value={formData.hadSurgery || ""}
              onChange={(e) => setFormData(prev => ({...prev, hadSurgery: e.target.value}))}
            >
              <FormControlLabel value="yes" control={<Radio />} label="是" />
              <FormControlLabel value="no" control={<Radio />} label="否" />
            </RadioGroup>
          </FormControl>
        </div>
      );
    case 2:
      return (
        <Grid container>
          <Grid sm={2} />
          <Grid lg={8} sm={8} spacing={10}>
            <Tooltip title="可在此填写咨询内容" placement="top-start" arrow>
              <TextField 
                label="咨询内容" 
                fullWidth 
                margin="normal" 
                rows={4} 
                multiline 
                variant="outlined" 
                placeholder="如有其他需求等,请在此填写"
                value={formData.consultation || ""}
                onChange={(e) => setFormData(prev => ({...prev, consultation: e.target.value}))}
              />
            </Tooltip>
          </Grid>
        </Grid>
      );
    case 3:
      // Convert raw values to readable text
      const genderText = formData.gender === "male" ? "男" : formData.gender === "female" ? "女" : "未填写";
      const birthDate = formData.birthYear && formData.birthMonth && formData.birthDay 
        ? `${parseInt(formData.birthYear) + 1989}年${formData.birthMonth}月${formData.birthDay}日`
        : "未填写";
      const yesNoText = (value) => value === "yes" ? "是" : value === "no" ? "否" : "未填写";

      return (
        <div style={{ lineHeight: "2.5", marginTop: 20 }}>
          <Typography variant="h6" gutterBottom>您填写的信息如下:</Typography>
          <div>
            <strong>- 性别 -</strong> {genderText}
          </div>
          <div>
            <strong>- 出生日期 -</strong> {birthDate}
          </div>
          <div>
            <strong>您目前是否已加入人寿保险?</strong> {yesNoText(formData.hasInsurance)}
          </div>
          <div>
            <strong>您目前是否正在住院?或者在3个月内,是否有过经医师诊断/检查后被建议住院或手术的情况?</strong> {yesNoText(formData.isHospitalized)}
          </div>
          <div>
            <strong>过去5年内,您是否因疾病或受伤接受过手术,或有过连续7天以上的住院经历?</strong> {yesNoText(formData.hadSurgery)}
          </div>
          <div style={{ marginTop: 10 }}>
            <strong>- 咨询内容 -</strong>
            <p style={{ marginLeft: 10, whiteSpace: "pre-wrap", marginTop: 5 }}>{formData.consultation || "未填写"}</p>
          </div>
        </div>
      );
    default:
      return "Unknown stepIndex";
  }
}

function Content() {
  const [activeStep, setActiveStep] = React.useState(0);
  // Initialize form data state
  const [formData, setFormData] = React.useState({
    gender: "",
    birthYear: "",
    birthMonth: "",
    birthDay: "",
    hasInsurance: "",
    isHospitalized: "",
    hadSurgery: "",
    consultation: ""
  });
  const steps = getSteps();

  const handleNext = () => {
    // Optional: Add validation here to block empty required fields
    setActiveStep((prevActiveStep) => prevActiveStep + 1);
  };

  const handleBack = () => {
    setActiveStep((prevActiveStep) => prevActiveStep - 1);
  };

  const handleReset = () => {
    setActiveStep(0);
    // Reset all form data
    setFormData({
      gender: "",
      birthYear: "",
      birthMonth: "",
      birthDay: "",
      hasInsurance: "",
      isHospitalized: "",
      hadSurgery: "",
      consultation: ""
    });
  };

  return (
    <Grid container>
      <Grid sm={2} />
      <Grid lg={8} sm={8} spacing={10}>
        <Stepper activeStep={activeStep} alternativeLabel>
          {steps.map((label) => (
            <Step key={label}>
              <StepLabel>{label}</StepLabel>
            </Step>
          ))}
        </Stepper>
        {activeStep === steps.length ? (
          <div>
            <Typography>所有步骤展示完成</Typography>
            <Button onClick={handleReset}>重置</Button>
          </div>
        ) : (
          <div>
            <Typography>{getStepContent(activeStep, { formData, setFormData })}</Typography>
            <Button disabled={activeStep === 0} onClick={handleBack} style={{ marginRight: 10 }}>
              返回
            </Button>
            <Button variant="contained" color="primary" onClick={handleNext}>
              {activeStep === steps.length - 1 ? "提交" : "下一步"}
            </Button>
          </div>
        )}
      </Grid>
    </Grid>
  );
}

export default Content;

Key Changes Explained

  • Form State Management: We added formData state to persist every user input. This ensures data stays intact as users navigate between steps.
  • Input Binding: Each form component now uses value to reflect the current state and onChange to update the state when the user interacts with it.
  • Confirmation Display: In case 3, we convert raw state values (like "male" or "yes") into user-friendly text and display each field with its original label.
  • Reset Functionality: The handleReset now clears both the active step and all form data, giving users a fresh start.

Optional Enhancements

  • Add form validation in handleNext to prevent users from advancing without filling required fields.
  • Use useReducer instead of useState if your form grows more complex (though useState works perfectly for this use case).

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 22:33:11