React Hook规则报错:如何让辅助函数可用Material-UI useStyles?
解决React Hook "useStyles"调用错误的问题
为什么会出现这个错误?
React Hooks的规则有两个核心要求:
- 只能在**React函数组件(首字母大写,且以
<ComponentName />的方式渲染)**的顶层调用Hook - 只能在**自定义Hook函数(必须以
use开头命名)**的顶层调用Hook
你的renderActions虽然返回JSX,但它是小写开头,并且是以普通函数renderActions(deleteVideo, id)的方式调用的,React不会把它识别为函数组件,所以在里面调用useStyles(这是makeStyles返回的自定义Hook)就违反了Hook的规则,导致报错。
如何把辅助函数当作组件使用?
最简单的方式是把renderActions改成标准的函数组件:
// 首字母大写,通过props接收参数 const Actions = ({ deleteVideo, id }) => { const classes = useStyles(); return ( <React.Fragment> <Button onClick={() => deleteVideo(id)} className={classes.button}>Delete</Button> </React.Fragment> ); }; // 在Delete组件中以组件标签的方式使用 const Delete = (props) => { const { deleteVideo, id } = props; const classes = useStyles(); // 这里需要调用useStyles获取modal的样式 return ( <Modal className={classes.modal} actions={<Actions deleteVideo={deleteVideo} id={id} />} /> ); };
这样修改后,Actions是符合规范的函数组件,就能合法调用useStyles了。另外注意原来的Delete组件里漏了调用useStyles,否则classes.modal会找不到,我已经补上了。
有没有更优的实现方式?
推荐上面的组件化方案,因为:
- 符合React组件化的设计思想,把可复用的UI片段封装成独立组件,更易维护、测试和复用
- 保持了Hook使用的规范性,避免后续出现更多Hook相关的错误
如果你的项目使用的是Material-UI v5,其实更推荐使用styled API或者sx prop来处理样式(makeStyles属于legacy API),比如用styled重构的话:
import { styled } from '@mui/material/styles'; import Button from '@mui/material/Button'; import Modal from '@mui/material/Modal'; const StyledButton = styled(Button)(({ theme }) => ({ backgroundColor: 'red', '&:hover': { backgroundColor: 'red', }, })); const StyledModal = styled(Modal)(({ theme }) => ({ backgroundColor: 'white', })); const Actions = ({ deleteVideo, id }) => { return ( <React.Fragment> <StyledButton onClick={() => deleteVideo(id)}>Delete</StyledButton> </React.Fragment> ); }; const Delete = (props) => { const { deleteVideo, id } = props; return ( <StyledModal actions={<Actions deleteVideo={deleteVideo} id={id} />} /> ); };
这种方式不需要使用useStyles Hook,直接通过styled组件封装样式,更贴合MUI v5的推荐用法,也避免了Hook规则的限制。
内容的提问来源于stack exchange,提问作者user11092881
相关产品推荐
相关产品推荐

