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

React中如何定义State/对象存储数据以调用POST API提交问卷答案

要实现这个需求,你可以按以下步骤修改代码,核心是用一个对象存储每个问题对应的选中答案ID,提交时再转换成API要求的格式:

1. 初始化存储选中答案的状态

用useState创建一个对象,键为问题ID,值为选中的答案ID,方便快速映射:

const [selectedAnswers, setSelectedAnswers] = useState({});

2. 修正单选按钮属性并添加选择事件

原代码里的单选按钮存在分组、值存储、标签关联的问题,调整后确保单选互斥、能正确捕获选中的答案ID:

{testQuestions.map((item) => {
  return (
    <div key={item.question.id}> {/* 添加key避免React警告 */}
      <h2>{item.question.title_text}</h2>

      {item.answers.map((sub) => {
        return (
          <div key={sub.id}> {/* 添加key */}
            <input
              type="radio"
              id={`answer-${sub.id}`}
              name={`question-${item.question.id}`} {/* 用问题ID分组,确保同一问题单选互斥 */}
              value={sub.id} {/* 存储答案ID,而非文本,方便后续提交 */}
              checked={selectedAnswers[item.question.id] === sub.id.toString()} {/* 标记当前选中状态 */}
              onChange={() => handleAnswerSelect(item.question.id, sub.id)}
            />
            <label htmlFor={`answer-${sub.id}`}>{sub.title_text}</label> {/* React中用htmlFor替代for */}
            <br />
          </div>
        );
      })}
    </div>
  );
})}

3. 实现选择变更处理函数

这个函数负责更新选中状态,将当前问题ID和对应的答案ID绑定:

const handleAnswerSelect = (questionId, answerId) => {
  setSelectedAnswers(prev => ({
    ...prev,
    [questionId]: answerId.toString() // 转字符串匹配input的value类型
  }));
};

4. 处理表单提交逻辑

在提交时,把selectedAnswers转换成API要求的数组格式,再发送POST请求:

const handleSubmit = async (e) => {
  e.preventDefault(); // 阻止表单默认跳转行为

  // 转换数据为API要求的格式
  const result = testQuestions.map(item => {
    const questionId = item.question.id;
    const answerId = selectedAnswers[questionId];
    
    // 简单校验:确保每个问题都已回答
    if (!answerId) {
      alert(`请完成问题:${item.question.title_text}`);
      return null;
    }

    return {
      questionId,
      answerId: parseInt(answerId), // 转数字匹配API的数值类型
      metricId: item.question.metric_id,
      subMetricId: item.question.sub_metric_id
    };
  }).filter(item => item !== null); // 过滤未回答的问题

  // 有未回答问题时终止提交
  if (result.length !== testQuestions.length) return;

  try {
    await axios.post('你的POST API地址', { result });
    alert('提交成功');
    // 可选:提交后重置选中状态
    setSelectedAnswers({});
  } catch (error) {
    console.error('提交失败:', error.message);
    alert('提交失败,请重试');
  }
};

最后给表单绑定提交事件:

<form className="App" onSubmit={handleSubmit}>
  {/* 原有表单内容 */}
  <button className="btn btn-default" type="submit">Submit</button>
</form>

完整修改后的代码

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

const Questionnaire = () => {
  const [testQuestions, setTestQuestions] = useState([]);
  const [selectedAnswers, setSelectedAnswers] = useState({});

  useEffect(() => {
    const fetchTestsQuestion = async () => {
      try {
        const { data } = await axios.get('你的GET API地址');
        setTestQuestions(data.questions);
      } catch (error) {
        console.error(error.message);
      }
    };

    fetchTestsQuestion();
  }, []);

  const handleAnswerSelect = (questionId, answerId) => {
    setSelectedAnswers(prev => ({
      ...prev,
      [questionId]: answerId.toString()
    }));
  };

  const handleSubmit = async (e) => {
    e.preventDefault();

    const result = testQuestions.map(item => {
      const questionId = item.question.id;
      const answerId = selectedAnswers[questionId];
      if (!answerId) {
        alert(`请回答问题:${item.question.title_text}`);
        return null;
      }
      return {
        questionId,
        answerId: parseInt(answerId),
        metricId: item.question.metric_id,
        subMetricId: item.question.sub_metric_id
      };
    }).filter(item => item !== null);

    if (result.length !== testQuestions.length) return;

    try {
      await axios.post('你的POST API地址', { result });
      alert('提交成功');
      setSelectedAnswers({});
    } catch (error) {
      console.error('提交失败:', error.message);
      alert('提交失败,请重试');
    }
  };

  return (
    <form className="App" onSubmit={handleSubmit}>
      {testQuestions.map((item) => {
        return (
          <div key={item.question.id} style={{ marginBottom: '20px' }}>
            <h2>{item.question.title_text}</h2>

            {item.answers.map((sub) => {
              return (
                <div key={sub.id} style={{ marginLeft: '10px' }}>
                  <input
                    type="radio"
                    id={`answer-${sub.id}`}
                    name={`question-${item.question.id}`}
                    value={sub.id}
                    checked={selectedAnswers[item.question.id] === sub.id.toString()}
                    onChange={() => handleAnswerSelect(item.question.id, sub.id)}
                  />
                  <label htmlFor={`answer-${sub.id}`}>{sub.title_text}</label>
                  <br />
                </div>
              );
            })}
          </div>
        );
      })}

      <button className="btn btn-default" type="submit">Submit</button>
    </form>
  );
};

export default Questionnaire;

关键说明

  • 用对象存储选中状态:键值对的形式能快速定位每个问题的选中答案,更新和读取效率高
  • 单选分组修正:通过name属性绑定问题ID,确保同一问题的选项互斥
  • 数据格式转换:提交时直接遍历原始问卷数据,结合选中状态生成API要求的结构,避免额外的数据处理
  • 基础校验:添加未回答提示,确保提交数据的完整性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 15:45:50