React类组件调用自定义Hook报错TypeError: Object(...) is not a function求助
报错截图:
错误成因
- 核心错误:在类组件
SimulatorContainer的render方法内调用自定义HookuseIdle,违反React Hook的使用规则。Hook仅允许在React函数组件的顶层作用域、自定义Hook的顶层作用域中调用,类组件内调用Hook会直接触发TypeError: Object(...) is not a function报错。 - 逻辑错误:
useIdle内部的active事件回调错误的将isIdle设为true,导致状态切换逻辑完全失效。 - 潜在兼容问题:若项目React版本低于16.8.0,本身不支持Hook特性,也会触发同类报错。
修复方案
推荐直接将现有类组件改造为函数组件,适配Hook的使用规则,改造后代码如下:
import React, { useState, useEffect } from 'react'; import { connect } from 'react-redux'; import * as Actions from '../actions'; import NeedContainer from './NeedContainer'; import ProfilContainer from './ProfilContainer'; import DealContainer from './DealContainer'; import AmountContainer from './AmountContainer'; import DurationContainer from './DurationContainer'; import MonthlyContainer from './MonthlyContainer'; import ContributionContainer from './ContributionContainer'; import FeesContainer from './FeesContainer'; import createActivityDetector from 'activity-detector' // 修正逻辑错误的自定义Hook function useIdle(time) { const [isIdle, setIsIdle] = useState(false) useEffect(() => { const activityDetector = createActivityDetector(time) activityDetector.on('idle', () => setIsIdle(true)) activityDetector.on('active', () => setIsIdle(false)) // 修正active事件的状态赋值 return () => activityDetector.stop() }, [time]) // 补充依赖项避免逻辑异常 return isIdle; } // 改造为函数组件 function SimulatorContainer(props) { const isIdle = useIdle({timeToIdle:1000}) // 可在此处添加isIdle对应的业务逻辑 if (!props.ready) return (<div className="wf-loading">Loading ...</div>); return ( <div className={props.className}> <NeedContainer /> <ProfilContainer /> <AmountContainer /> <ContributionContainer /> <DurationContainer /> <MonthlyContainer /> <DealContainer /> <FeesContainer /> </div> ); } const mapStateToProps = state => { return { ready:state.simulator.ready, interest:state.simulator.interest, } } const mapDispatchToProps = dispatch => { return { isReady: (ready) => { dispatch(Actions.isReady(ready)); } } } export default connect( mapStateToProps, mapDispatchToProps )(SimulatorContainer)
如果不想改造类组件,可以把空闲检测逻辑迁移到类组件的生命周期中实现:
- 在
componentDidMount中初始化activityDetector,绑定事件回调修改组件state的isIdle状态 - 在
componentWillUnmount中调用activityDetector.stop()销毁实例 - 移除自定义Hook的相关代码即可
内容的提问来源于stack exchange,提问作者agoumi
相关产品推荐
相关产品推荐

