React调用自定义GetColor函数报Invalid Hook Call错误如何解决
React Hook调用错误修复说明
核心错误原因
你触发报错的根本原因是违反了React的Hook调用规则,具体存在3个问题:
- 你当前的业务组件是类组件(代码中存在
this.state、this.setState、render类组件专属语法),而Hook只能在函数组件中使用,类组件不支持任何Hook调用。 - 你封装的
GetColor是普通JS函数,不符合自定义Hook的命名规范:React要求自定义Hook必须以use开头,否则不会被识别为Hook,无法使用Hook相关能力。 - 你调用
GetColor的位置是类组件的setState参数、render方法内部,都不属于合法的Hook调用上下文。
另外你的useEffect没有配置依赖数组,即使Hook调用合法也会进入无限请求的死循环。
Hook使用必守规则
- 仅能在React函数组件、以use开头命名的自定义Hook的顶层作用域调用Hook
- 不能在类组件、普通JS函数、条件判断、循环、回调函数、异步逻辑中调用Hook
useEffect必须配置对应的依赖数组,避免重复执行或取值异常
修复方案
方案1:保留现有类组件,移除Hook逻辑(改造成本最低)
把GetColor改造成普通异步函数,在类组件的生命周期中调用后将结果存入state:
// 修改后的GetColor.js import SiteReportCardMasterService from '../Services/SiteReportCardMasterService'; const GetColor = async (id,rptvalue) => { const res = await SiteReportCardMasterService.getSiteReportCardMasterById(id) if (rptvalue === 0) return res.data.sitereportcardmasterColore if (rptvalue < 70) return res.data.sitereportcardmasterColord if (rptvalue >= 70 && rptvalue <80) return res.data.sitereportcardmasterColorc if (rptvalue >= 80 && rptvalue <90) return res.data.sitereportcardmasterColorb if (rptvalue >= 90) return res.data.sitereportcardmasterColora }; export default GetColor;
类组件中在componentDidMount生命周期调用:
componentDidMount() { GetColor(127,90).then(color => { this.setState({fcolor: color}) }) } render(){ return( <h2 className="text-center">{this.state.fcolor}</h2> <td style={{color: this.state.fcolor}} >{this.state.fcolor} </td> ) }
方案2:将类组件重构为函数组件,使用合规自定义Hook
首先将GetColor重命名为useGetColor符合自定义Hook规范:
// 修改后的useGetColor.js import { useEffect, useState } from "react"; import SiteReportCardMasterService from '../Services/SiteReportCardMasterService'; const useGetColor = (id,rptvalue) => { const [color, setColor] = useState('') useEffect(() =>{ SiteReportCardMasterService.getSiteReportCardMasterById(id).then( (res) =>{ if (rptvalue === 0) setColor(res.data.sitereportcardmasterColore) if (rptvalue < 70) setColor(res.data.sitereportcardmasterColord) if (rptvalue >= 70 && rptvalue <80) setColor(res.data.sitereportcardmasterColorc) if (rptvalue >= 80 && rptvalue <90) setColor(res.data.sitereportcardmasterColorb) if (rptvalue >= 90) setColor(res.data.sitereportcardmasterColora) }) // 配置依赖数组,只有id、rptvalue变化时才重新请求 }, [id, rptvalue]) return color }; export default useGetColor;
重构后的函数组件调用示例:
import useGetColor from './useGetColor' function YourComponent() { // 在函数组件顶层调用自定义Hook const fcolor = useGetColor(127,90) return ( <> <h2 className="text-center">{fcolor}</h2> <td style={{color: fcolor}} >{fcolor} </td> </> ) }
内容的提问来源于stack exchange,提问作者HighwayRob
相关产品推荐
相关产品推荐

