Material UI Popover如何不使用Hook实现弹出,解决Hook渲染数量不一致报错
方案1:CSS hover实现(最推荐,性能最优)
你的交互仅为鼠标悬停触发展示,无需JS管理状态,直接用CSS控制显隐即可完全规避Hook相关问题:
import React from 'react'; import Box from '@material-ui/core/Box'; import ImageCell from 'App/components/DatabaseTable/Utils/ImageCell'; const Image = ({ defaultValueRow, valueRow }) => { const id = `popover-${defaultValueRow[valueRow]}`; const imgSrc = valueRow[defaultValueRow]; return ( <Box sx={{ position: 'relative', '&:hover .hover-popover': { display: 'block' } }} aria-haspopup="true" aria-owns={id} > <Box> <ImageCell src={imgSrc} /> </Box> <Box id={id} className="hover-popover" sx={{ pointerEvents: 'none', position: 'absolute', padding: '8px', bottom: '100%', left: '50%', transform: 'translateX(-50%)', display: 'none', zIndex: 9999, bgcolor: 'background.paper', borderRadius: 1, boxShadow: 3 }} > <ImageCell style={{ maxWidth: '125rem', maxHeight: '15rem' }} src={imgSrc} /> </Box> </Box> ); }; export default Image;
方案2:重写为类组件(兼容MUI Popover原生能力)
如果需要保留MUI Popover的所有原生特性(如自动边界检测、定位、层级处理等),可以将组件改写为类组件,用类内部状态管理anchorEl,完全不涉及Hook调用:
import React, { Component } from 'react'; import Box from '@material-ui/core/Box'; import Popover from '@material-ui/core/Popover'; import ImageCell from 'App/components/DatabaseTable/Utils/ImageCell'; class Image extends Component { state = { anchorEl: null }; handlePopoverOpen = (event) => { this.setState({ anchorEl: event.currentTarget }); }; handlePopoverClose = () => { this.setState({ anchorEl: null }); }; render() { const { defaultValueRow, valueRow } = this.props; const { anchorEl } = this.state; const id = `popover-${defaultValueRow[valueRow]}`; const imgSrc = valueRow[defaultValueRow]; return ( <> <Box aria-haspopup="true" aria-owns={anchorEl ? id : undefined} onMouseEnter={this.handlePopoverOpen} onMouseLeave={this.handlePopoverClose} > <ImageCell src={imgSrc} /> </Box> <Popover id={id} style={{ pointerEvents: 'none' }} PaperProps={{ style: { padding: '8px' }, }} open={Boolean(anchorEl)} anchorEl={anchorEl} anchorOrigin={{ vertical: 'top', horizontal: 'center', }} transformOrigin={{ vertical: 'bottom', horizontal: 'center', }} > <ImageCell style={{ maxWidth: '125rem', maxHeight: '15rem' }} src={imgSrc} /> </Popover> </> ); } } export default Image;
补充说明
你遇到的Rendered more hooks than during the previous render报错本质并非useState本身导致,而是该组件的Hook调用次数/顺序在重渲染前后不一致,通常是由上层条件渲染、或组件内部Hook调用前存在提前return逻辑导致。如果后续需要使用Hook,可优先排查上述问题。
内容的提问来源于stack exchange,提问作者Sonhja
相关产品推荐
相关产品推荐

