React HOC组件回调失效 报setActive不是函数如何解决
问题产生原因
报错核心是3处写法错误共同导致的:
- HOC中
open/close传值逻辑错误:代码里写的open={() => open}、close={() => close}仅在箭头函数里返回了内部定义的open/close函数引用,既不接收传入参数,也不会实际执行弹窗开关的逻辑。 - 事件绑定时机错误:ButtonsOur组件里写的
Click={open(setActive)}属于渲染阶段立即执行的写法,页面首次加载渲染时就会直接调用open方法,而非用户点击按钮时才触发。 - 参数传递逻辑倒置:setActive是父组件传入的状态更新方法,渲染阶段执行
open(setActive)时,仅拿到了HOC中箭头函数返回的内部open函数引用,并没有实际调用该函数,后续点击触发时根本拿不到正确的setActive引用,最终抛出类型错误。
修复方案
优先推荐逻辑更清晰的HOC直接接管状态调用的写法,修改两个文件即可:
- 修正HOC代码,直接从接收的props中取setActive,调整属性传递顺序,去掉无意义的函数包装:
const HOC = (Component) => { function HandleChange(props) { // 直接从父组件传入的props中解构setActive const { setActive } = props; function open() { setActive(true); } function close() { setActive(false); } return ( <Component // 先展开父组件原始props {...props} // 后注入HOC封装的开关方法,避免被父组件同名属性覆盖 open={open} close={close} /> ); } return HandleChange; }; export default HOC;
- 修正ButtonsOur组件的事件绑定,传入回调函数而非直接执行方法,避免渲染阶段提前触发状态更新:
import HOC from '../../../hoc/HocPopUp'; function ButtonsOur({ setActive, open }) { return ( <div className="base__routes__button"> {/* 绑定箭头函数作为点击回调,点击时才执行open逻辑 */} <Buttons className="base__button__moreInf open-popup-exc" Click={() => open()}>Докладніше</Buttons> <Buttons className="base__button__moreInf open-popup-exc" Click={() => open()}>Забронювати</Buttons> </div> ); } export default HOC(ButtonsOur);
注:原代码第二个Buttons的className存在多余空格open-popu p-exc,已修正为和第一个按钮一致的正确类名。
可选兼容写法
如果需要保留「调用open时手动传入setActive」的编码习惯,可以把HOC里的open/close改为柯里化形式,返回绑定好参数的点击回调,不需要修改ButtonsOur里的事件传参写法:
const HOC = (Component) => { function HandleChange(props) { // 柯里化:接收setActive参数后返回点击时执行的回调 function open(setActive) { return () => setActive(true); } function close(setActive) { return () => setActive(false); } return ( <Component {...props} close={close} open={open} /> ); } return HandleChange; }; export default HOC;
这种写法下Click={open(setActive)}会在渲染阶段返回一个绑定了正确setActive引用的回调函数,点击时才会触发状态更新,也能正常运行。
内容的提问来源于stack exchange,提问作者Anta
相关产品推荐
相关产品推荐

