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

点击按钮传ID调用API获取数据时遇无效Hook调用错误求助

修复React无效Hook调用的问题

问题根源

你直接通过onClick={() => EditExercise(item.idexercise)}调用EditExercise函数,但这个函数内部使用了useState、useEffect等Hook。React的Hook规则明确要求:Hook只能在React函数组件的顶层,或者自定义Hook的顶层调用,在事件回调里直接调用包含Hook的函数会违反这个规则,导致无效Hook调用的错误。

修复方案

1. 父组件改用状态控制编辑组件的渲染

在你的index.js里,添加一个状态来记录选中的编辑ID,点击按钮时更新这个状态,然后通过条件渲染的方式加载EditExercise组件,而不是直接调用函数。

修改后的父组件示例:

import { useState } from 'react';
import EditExercise from './EditExercise';

function ExerciseList() {
  const [exercises, setExercises] = useState([]);
  // 新增状态:记录选中要编辑的ID
  const [selectedEditId, setSelectedEditId] = useState(null);

  // 原有的获取列表数据逻辑...

  return (
    <div>
      {/* 渲染数据行 */}
      {exercises.map(item => (
        <div key={item.idexercise}>
          <span>{item.exerciseName}</span>
          {/* 点击时设置选中ID,而非直接调用EditExercise */}
          <button onClick={() => setSelectedEditId(item.idexercise)}>编辑</button>
        </div>
      ))}

      {/* 当有选中ID时,渲染编辑组件 */}
      {selectedEditId && <EditExercise id={selectedEditId} />}
    </div>
  );
}

2. 修正EditExercise组件的细节问题

同时,你的EditExercise组件还有几个小问题需要调整:

  • 模板字符串要用反引号,否则变量id不会被解析
  • input标签需要用value属性绑定数据,不能直接把内容作为子节点
  • useEffect的依赖数组要加入id,确保ID变化时重新发起请求
  • 初始化item用空对象更合理(因为返回的是单个数据对象)

修改后的EditExercise.jsx示例:

import { useState, useEffect } from 'react';

// 改为通过props接收id
function EditExercise({ id }) {
    const [error, setError] = useState(null);
    const [isLoaded, setIsLoaded] = useState(false);
    const [item, setItem] = useState({});

    useEffect(() => {
        // 用反引号包裹模板字符串
        fetch(`http://localhost:5000/Exercises/GetEditId?id=${id}`)
        .then(res => {
            // 额外添加请求成功校验
            if (!res.ok) throw new Error('请求出错');
            return res.json();
        })
        .then(
            (result) => {
                setIsLoaded(true);
                setItem(result);
            },
            (error) => {
                setIsLoaded(true);
                setError(error);
            }
        )
    }, [id]) // 加入id到依赖数组,触发重新请求

    if (error) {
        return <div>Error: {error.message}</div>;
    } else if (!isLoaded) {
        return <div>Loading...</div>;
    } else {
        return (
            <div>
                {/* 用value绑定数据,闭合input标签 */}
                <input type="text" id="name" value={item.exerciseName || ''} />
                <input type="text" id="desc" value={item.instructions || ''} />
            </div>
        );
    }
}

export default EditExercise;

为什么这么改

React需要追踪Hook的调用顺序,确保每次渲染时Hook的调用顺序一致。直接在事件回调里调用包含Hook的函数,会让Hook的调用脱离React的组件渲染流程,导致React无法正确追踪,从而抛出无效Hook调用的错误。通过条件渲染组件的方式,EditExercise会作为正常的React组件被渲染,Hook也会在组件的顶层被调用,符合规则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 15:53:37