React点击触发封装的Modal模块时报无效Hook调用错误如何解决
问题根源
你当前报错属于违反Hook使用规则的场景:Upload_img是内置了useState的React函数组件,你将它直接作为onClick的回调函数执行,此时函数没有走React的组件渲染流程,属于普通函数调用,内部的Hook自然不符合「仅可在函数组件顶层调用」的规则,因此抛出错误。
解决方案
提供两种常用实现方式,可按需选择:
方案1:声明式写法(推荐,符合React设计理念)
将Modal的显示状态提升到父组件管理,点击时修改状态控制组件渲染:
// Header.js import React, { useState } from "react"; import Upload_img from "./Upload_img"; function Header() { // 父组件维护Modal显示状态 const [showUploadModal, setShowUploadModal] = useState(false); return ( <div className="header__search"> <ImageSearchIcon onClick={() => setShowUploadModal(true)}/> {/* 状态为真时渲染Modal组件 */} {showUploadModal && <Upload_img open={showUploadModal} onClose={() => setShowUploadModal(false)} />} </div> ); } export default Header;
调整Upload_img组件接收父组件传递的控制参数:
// Upload_img.js import React from "react"; import Modal from '@material-ui/core/Modal'; const Upload_img = ({ open, onClose }) => { return ( <div> <Modal open={open} onClose={onClose}> <h1>hello</h1> </Modal> </div> ) } export default Upload_img
方案2:命令式调用写法
如果希望保持直接调用函数弹出弹窗的使用方式,可通过动态渲染实现:
// Upload_img.js import React from "react"; import ReactDOM from "react-dom"; import Modal from '@material-ui/core/Modal'; // 封装为可直接调用的函数 const Upload_img = () => { const mountNode = document.createElement('div'); document.body.appendChild(mountNode); const ModalContent = () => { const [open, setOpen] = React.useState(true); const handleClose = () => { setOpen(false); // 关闭时卸载节点 ReactDOM.unmountComponentAtNode(mountNode); document.body.removeChild(mountNode); }; return ( <Modal open={open} onClose={handleClose}> <h1>hello</h1> </Modal> ) } ReactDOM.render(<ModalContent />, mountNode); } export default Upload_img
该方案下Header组件的调用逻辑不用修改,保持原代码即可。
其他异常排查
如果修改后仍存在报错,再排查以下两个场景:
- 检查React与ReactDOM版本是否匹配,执行
npm ls react react-dom查看两者版本号,不一致的话安装同版本即可修复 - 检查是否存在多份React副本,可执行
npm dedupe合并重复依赖解决
内容的提问来源于stack exchange,提问作者greenapple
相关产品推荐
相关产品推荐

