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

基于JSON的测验应用如何实现返回按钮返回上一已选步骤

测验应用返回上一步功能实现方案

核心实现依赖步骤历史栈记录用户的访问路径,不需要额外在接口数据里反向查询步骤关联,实现逻辑简单可靠:

  • 新增状态存储全量步骤数据,避免每次跳转/返回都重复发接口请求
  • 新增状态维护浏览历史栈,栈的顺序和用户访问步骤的顺序完全一致
  • 正向跳转时将新步骤ID压入栈顶,再加载对应步骤内容
  • 返回时判断栈长度,非初始页就弹出当前栈顶ID,取新的栈顶ID加载上一步内容,同时同步单选框的选中状态

修正后可直接参考的代码

import { useState, useEffect } from 'react'
import axios from 'axios'

// 可根据实际数据结构调整类型
type StepOption = {
  optionTitle: string
  destinationStepId: string
}
type Step = {
  id: string
  title: string
  type: 'qs' | 'instruction'
  options?: StepOption[]
  instruction?: string
}

const QuizApp = () => {
  const [allSteps, setAllSteps] = useState<Step[]>([])
  // 当前展示的步骤数据
  const [currentStepData, setCurrentStepData] = useState<Step | null>(null)
  // 步骤历史栈,初始值替换成实际第一道题的步骤ID
  const [stepHistory, setStepHistory] = useState<string[]>(['step-1'])
  const [isChecked, setIsChecked] = useState<string | null>(null)

  // 组件初始化时只拉一次全量步骤数据
  useEffect(() => {
    axios.get('http://localhost:5000/steps').then((res) => {
      setAllSteps(res.data)
      // 加载初始步骤
      const firstStep = res.data.find((item: Step) => item.id === stepHistory[0])
      setCurrentStepData(firstStep)
    })
  }, [])

  // 正向跳转到指定步骤
  const navigateTo = (targetStepId: string) => {
    const targetStep = allSteps.find((item) => item.id === targetStepId)
    if (!targetStep) return
    // 新步骤压入历史栈
    setStepHistory(prev => [...prev, targetStepId])
    setCurrentStepData(targetStep)
    setIsChecked(targetStepId)
  }

  // 返回上一步
  const navigateBack = () => {
    // 历史栈长度大于1才允许返回,避免在首页点返回报错
    if (stepHistory.length <= 1) return
    // 复制历史栈,弹出当前所在的步骤ID
    const newHistory = [...stepHistory]
    newHistory.pop()
    // 新的栈顶就是上一步的ID
    const prevStepId = newHistory[newHistory.length - 1]
    const prevStep = allSteps.find((item) => item.id === prevStepId)
    if (!prevStep) return
    
    setStepHistory(newHistory)
    setCurrentStepData(prevStep)
    // 同步上一步的选中状态
    setIsChecked(prevStepId)
  }

  const handleStepChange = (destinationStepId: string) => {
    navigateTo(destinationStepId)
  }

  if (!currentStepData) return <div>加载中...</div>

  return (
    <div>
      <div>{currentStepData.title}<br /></div>
      {currentStepData.type === "qs" ?
        currentStepData.options?.map((step, index) => (
          <div key={index}>
            <input 
              type="radio" 
              onChange={() => handleStepChange(step.destinationStepId)}
              name="stepOption" 
              checked={isChecked === step.destinationStepId} 
            />
            {step.optionTitle}
          </div>
        )) :
        currentStepData.instruction
      }
      {/* 返回按钮,在首页时自动禁用 */}
      <button 
        onClick={navigateBack}
        disabled={stepHistory.length <= 1}
        style={{ marginTop: '20px' }}
      >
        返回上一步
      </button>
    </div>
  )
}

export default QuizApp

如果测验需要支持返回后修改选项、重新选择走不同分支,现有逻辑已经兼容——用户重新选择选项时会把新步骤压入栈,不会影响历史记录的正确性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.14 16:15:48