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

React自定义Hook onClick传参触发规则报错,求问题原因及修正方案

问题分析与解决

问题描述

我开发了一个简单的React应用,通过jsonplaceholder API获取数据并展示,每条数据对应一个删除按钮。原本在User.js组件内实现了deleteUser函数,现希望将该函数封装为通用自定义Hook,但在向该Hook传参时触发如下错误:

React Hooks must be called in a React function component or a custom React Hook function react-hooks/rules-of-hooks

相关代码如下:

userDelete.js

import { useFetch } from "./useFetch";
export const useDelete = (userName) => {
  const { data, setData} = useFetch();
  const newData = data.filter((dataItem) => dataItem.name !== userName);
  console.log(newData);
  setData(newData)
};

useFetch.js

import { useState, useEffect } from "react";

export const useFetch = () => {
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState([]);
  const url = `https://jsonplaceholder.typicode.com/users`;
  const fetchData = async () => {
    try {
      setLoading(true);
      const response = await fetch(url);
      const data = await response.json();
      console.log(data);
      setData(data);
      setLoading(false);
      return;
    } catch (error) {
      console.log("Error", error);
    }
  };
  useEffect(() => {
    fetchData();
  }, []);
  return { loading, data, setData };
};

User.js

import { useFetch } from "../Hooks/useFetch";
import { useDelete } from "../Hooks/useDelete";

const Users = () => {
  const { loading, data, setData } = useFetch();
  const deleteCallback = useDelete(data);

  const deleteUser = (userName) => {
    const newData = data.filter((dataItem) => dataItem.name !== userName);
    console.log("newData", newData);
    setData(newData);
  };
  return (
    <>
      <h1>Custom Hook Example</h1>
      {loading && <h4>Fetching Data...</h4>}
      {data.map((data, index) => (
        <div
          key={index}
          style={{
            border: "2px solid red",
            width: "fit-content",
            margin: "0 auto"
          }}
        >
          <p>Name: {data.name}</p>
          <article>Email: {data.email}</article>
          {/* <button onClick={(e) => deleteUser(data.name, e)}>Delete</button> */}
          <button onClick={() => useDelete(data.name)}>Delete</button>
        </div>
      ))}
      {data.length === 0 && (
        <>
          <p>No Items to Show</p>
        </>
      )}
    </>
  );
};

export default Users;

错误原因

  • 违反Hook调用规则:在按钮的onClick事件回调中直接调用useDelete(data.name),Hook只能在React函数组件或自定义Hook的顶层作用域调用,不能在事件处理、循环、条件判断等嵌套逻辑里执行。
  • 自定义Hook逻辑冗余:useDelete内部重复调用useFetch,会导致每次执行删除时都重新发起API请求,且和组件中useFetch维护的状态是独立的,完全不符合复用删除逻辑的需求。

修正方案

重构useDelete Hook

让它接收组件中的data和setData作为参数,返回一个可复用的删除函数,而不是直接执行删除操作:

// userDelete.js
export const useDelete = (data, setData) => {
  const deleteUser = (userName) => {
    const newData = data.filter(item => item.name !== userName);
    setData(newData);
  };

  return deleteUser;
};

修改User.js组件

在组件顶层调用useDelete,获取删除函数后绑定到按钮点击事件:

// User.js
import { useFetch } from "../Hooks/useFetch";
import { useDelete } from "../Hooks/useDelete";

const Users = () => {
  const { loading, data, setData } = useFetch();
  // 在组件顶层调用自定义Hook,传入数据和更新函数
  const deleteUser = useDelete(data, setData);

  return (
    <>
      <h1>Custom Hook Example</h1>
      {loading && <h4>Fetching Data...</h4>}
      {data.map((item, index) => (
        <div
          key={index}
          style={{
            border: "2px solid red",
            width: "fit-content",
            margin: "0 auto"
          }}
        >
          <p>Name: {item.name}</p>
          <article>Email: {item.email}</article>
          {/* 调用返回的删除函数,传入用户名 */}
          <button onClick={() => deleteUser(item.name)}>Delete</button>
        </div>
      ))}
      {data.length === 0 && (
        <>
          <p>No Items to Show</p>
        </>
      )}
    </>
  );
};

export default Users;

useFetch.js保持原有代码不变即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 11:54:20