React组件调用时触发Invalid Hook Call错误的排查求助
问题原因
你在Card组件的按钮点击事件里直接调用了ProductCompare(product),这相当于把React组件当成普通JavaScript函数执行了。React Hooks必须在组件的渲染上下文中使用,直接调用组件函数会让Hooks脱离React的组件生命周期管理,从而触发"Invalid hook call"错误。
修复方案
1. 修改Card组件,通过状态控制对比组件的显示
在Card组件中添加状态来控制ProductCompare的渲染,而不是直接调用组件函数:
import React, { useState } from "react"; import Imagehelper from "./helper/Imagehelper"; import ProductCompare from "./ProductCompare"; const isAuthenticated = true; const Card = ({ product, addtoCart = true, removefromCart = true }) => { const [showCompare, setShowCompare] = useState(false); const productTitle = product ? product.subbranch3 : "نام محصول"; const productdescription = product ? product.goodproperties : "توضیحات محصول"; const productPrice = product ? product.price : "قیمت محصول"; const addToCart = () => { if (isAuthenticated) { console.log("محصول به سبد خرید اضافه شد"); } else { console.log("لطفا وارد حساب کاربری خود شوید"); } }; const showAddToCart = (addtoCart) => { return ( addtoCart && ( <button onClick={addToCart} className="btn btn-outline-success mt-2 mb-2" > افزودن به سبد خرید </button> ) ); }; const showRemoveFromCart = (removefromCart) => { return ( removefromCart && ( <button onClick={() => { console.log("محصول از سبد خرید حذف شد"); }} className="btn btn-outline-danger mt-2 mb-2" > حذف از سبد خرید </button> ) ); }; return ( <div className="card text-white bg-dark border border-info" dir="rtl"> <div className="card-header lead">{productTitle}</div> <div className="card-body"> <Imagehelper product={product} /> <p className="lead bg-success font-weight-normal text-wrap"> {productdescription} </p> <p className="btn btn-block btn-success rounded btn-sm px-4"> {productPrice}تومان </p> <div className="row"> <div className="col-12">{showAddToCart(addtoCart)}</div> <div className="col-12">{showRemoveFromCart(removefromCart)}</div> <div className="col-12"> <button className="btn btn-block btn-outline-info mt-2 mb-2" onClick={() => setShowCompare(!showCompare)} > compare product </button> </div> </div> {showCompare && <ProductCompare product={product} />} </div> </div> ); }; export default Card;
2. 修正ProductCompare组件的props接收和依赖问题
ProductCompare组件接收的是props对象,需要正确解构;同时第二个useEffect的依赖项缺失,导致筛选逻辑不会更新:
import React, { useState, useEffect } from "react"; import { getProductsAttribute } from "./helper/Coreapicalls"; import Imagehelper from "./helper/Imagehelper"; const ProductCompare = ({ product }) => { console.log("product is:", product); const [allproductsAttribute, setAllProductsAttribute] = useState([]); const [singleProductAttributes, setSingleProductAttributes] = useState([]); const [error, setError] = useState(false); const productID = product?.id; const loadAllProductAttribute = () => { getProductsAttribute().then((data) => { if (data.error) { setError(data.error); console.log(data.error); } else { setAllProductsAttribute(data); } }); }; useEffect(() => { loadAllProductAttribute(); }, [product]); console.log("product attributes are:", allproductsAttribute); console.log(error); const loadSingleProductAttributes = () => { if (!productID) return; setSingleProductAttributes( allproductsAttribute.filter((pa) => pa.good === productID) ); }; useEffect(() => { loadSingleProductAttributes(); }, [allproductsAttribute, productID]); return ( <div className="row" dir="rtl"> <div className="col-3 mb-3"> <div className="row"> <Imagehelper product={product} /> </div> <div className="row"> {singleProductAttributes.map((value, index) => { return ( <div key={index} className="col-4 mb-4"> <p className="text-white">{JSON.stringify(value)}</p> </div> ); })} </div> </div> </div> ); }; export default ProductCompare;
额外说明
- React组件必须通过JSX语法(
<Component />)渲染,不能像普通函数一样直接调用,否则Hooks无法正常工作。 - 确保所有useEffect的依赖项完整,避免出现 stale state 问题。
- 使用可选链(
product?.id)可以避免当product为undefined时报错。
内容的提问来源于stack exchange,提问作者Mohammad Asadi
相关产品推荐
相关产品推荐

