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

React中创建可复用API请求函数的方法及最佳实践咨询

问题描述

需要在独立JavaScript文件中创建可复用函数,通过GET方法向API传递两个参数(JSON格式),获取返回的JSON数据并在home.js中使用,同时想了解React中的最佳实践。

请求参数格式:

{ "exam_id": 1, "question_id": 22 }

预期返回格式:

[
    {
        "Choice_1": "choice 1",
        "Choice_2": "choice 2",
        "Choice_3": "choice 3",
        "Choice_4": "choice 4",
        "Choice_5": "choice 5",
        "Question": "This field represents the question to be asked.",
        "QuestionID": 22,
        "Scenario": "something needed to expand on the question asked.",
        "Answer": "correct answer for question."
    }
]

当前环境:Windows、VSCode、React 18.3.1、npm 10.8.0、npx 10.8.0

现有Question.js代码无法运行:

import React from 'react';

function GetQuestion() {
    
    const fetchData = async () => {
        const request_url = 'http://127.0.0.1:5000/exam/question';
        const request_json= '{"exam_id": '+{exam_id}+', "question_id": '+{question_id}+'}';
        const request={request_url} + '?' + {request_json};
        const response = await fetch(request);
        const response_data = await response.json();
        setData(response_data);
    };

    return fetchData()
}

export default GetQuestion;

问题修复与React最佳实践

一、现有代码的核心错误

  1. 参数未传入:exam_id和question_id未作为函数参数传入,直接引用会引发未定义错误
  2. GET参数格式错误:GET请求不能直接拼接JSON字符串到URL,需转为标准查询参数(如?exam_id=1&question_id=22)
  3. 状态缺失:setData未对应声明useState变量
  4. 逻辑循环:组件渲染时直接返回fetchData()会触发无限调用接口

二、React中的标准实现方案

1. 独立封装API请求模块

将API逻辑与组件解耦,放在单独的api/questions.js文件,方便多组件复用:

// api/questions.js
const BASE_URL = process.env.REACT_APP_API_URL || 'http://127.0.0.1:5000';

export const fetchQuestion = async (examId, questionId) => {
  const url = new URL(`${BASE_URL}/exam/question`);
  // 添加标准查询参数
  url.searchParams.append('exam_id', examId);
  url.searchParams.append('question_id', questionId);

  const response = await fetch(url.toString());
  
  // 处理HTTP错误
  if (!response.ok) {
    throw new Error(`请求失败: ${response.statusText}`);
  }

  return await response.json();
};

2. 封装自定义Hook处理React状态

在hooks/useQuestion.js中封装加载、错误、数据状态,简化组件逻辑:

// hooks/useQuestion.js
import { useState, useEffect } from 'react';
import { fetchQuestion } from '../api/questions';

export const useQuestion = (examId, questionId) => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const loadQuestion = async () => {
    setLoading(true);
    setError(null);
    try {
      const result = await fetchQuestion(examId, questionId);
      setData(result);
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };

  // 参数变化时自动重新请求
  useEffect(() => {
    if (examId && questionId) {
      loadQuestion();
    }
  }, [examId, questionId]);

  return { data, loading, error, refetch: loadQuestion };
};

3. 在Home组件中使用自定义Hook

// Home.js
import { useQuestion } from './hooks/useQuestion';

function Home() {
  // 根据业务逻辑动态传入参数
  const { data, loading, error, refetch } = useQuestion(1, 22);

  if (loading) return <div>加载中...</div>;
  if (error) return <div>出错了: {error}</div>;
  if (!data) return <div>无数据</div>;

  const question = data[0];
  return (
    <div className="question-container">
      <h3>{question.Question}</h3>
      <p className="scenario">{question.Scenario}</p>
      <ul className="choices">
        <li>{question.Choice_1}</li>
        <li>{question.Choice_2}</li>
        <li>{question.Choice_3}</li>
        <li>{question.Choice_4}</li>
        <li>{question.Choice_5}</li>
      </ul>
      <button onClick={refetch}>重新加载</button>
    </div>
  );
}

export default Home;

三、额外最佳实践建议

  • 取消请求:组件卸载时用AbortController取消未完成的请求,避免内存泄漏
  • 参数校验:在API函数中添加参数合法性检查,比如验证examId和questionId为有效数字
  • 环境变量:用.env文件存储API地址(如REACT_APP_API_URL),方便不同环境切换
  • 全局错误处理:可封装全局的错误捕获逻辑,统一处理API请求异常

四、关于GET请求传JSON的说明

GET请求优先使用标准查询参数格式,若后端强制要求传JSON,可将JSON编码后作为单个查询参数值:

const params = encodeURIComponent(JSON.stringify({ exam_id: 1, question_id: 22 }));
const url = `${BASE_URL}/exam/question?data=${params}`;

但这种方式不符合HTTP规范,不推荐使用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 13:44:51