我正在使用react-admin
框架。我编写了自定义组件,该组件在materialUI GridList
中显示图像。我必须实现useState
函数来确定如果用户将鼠标悬停在特定的Button
上要显示的元素。但是,在实施useState
后,应用程序崩溃并出现以下错误:
Error: Rendered fewer hooks than expected. This may be caused by an accidental early return statement.
我的代码:
const [mouseOver, setMouseOver] = useState(false);
const onButtonHover = () =>
{
setMouseOver(true);
}
const onButtonClose = () =>
{
setMouseOver(false);
}
return <GridListTile key={id} onMouseLeave={onButtonClose} {...tileProps}>
<img src={ImageService.getUrl(image)} className={classes.pngbgr} alt={title} />
{mouseOver ?
<div className={classes.tagsContainer}>
<TagsShow source="tags" record={record} />
</div>
:
null
}
<GridListTileBar
className={classes.tileBar}
title={title}
subtitle={tags !== undefined && tags.length > 0 ?
<Button className={classes.tagsButton} onMouseOver={onButtonHover} label="hf.action.showTags"><LabelIcon /></Button>
:
null
}
/>
</GridListTile>;
然后我在我的Gallery模型中渲染我的组件:
const GalleryList = props => (
<List filters={<GalleryFilter />} pagination={<ListPagination />} perPage={30} sort={{ field: '_id', order: 'ASC' }} actions={<Actions />} {...props}>
<GridList rowClick="show" getTileProps={getGalleryTileProps} />
</List>
);
有什么主意我为什么会出现此错误?
谢谢。
答案 0 :(得分:0)
This article by Kent C Dodds可能相关。
如果没有更多关于如何使用自定义组件的详细信息,不能确定这是您的答案-但看起来违反了以下钩子规则(摘自本文)
您需要确保对于给定的组件,挂钩总是被调用相同的次数。
换句话说,如果您使用组件作为函数调用,请说出这样的话:
return arr.map(CustomComponent)
...由于它是被调用而不是“渲染”的,因此该组件的钩子将在父组件的范围内进行解释-它将转换为类似这样的内容...
const ParentComponent() {
return arr.map((item) => {
// no. of hooks in ParentComponent depends on number of items
const [mouseOver, setMouseOver] = useState(false);
.. rest of your component
}
}
...违反了上面提到的钩子规则。
替换为:
arr.map((item) => <CustomComponent item={item}/>)
使React将钩子解释为自定义组件范围的一部分,并且它们不会引发此错误。
希望这会有所帮助!
更新
在此处添加后代更新
有问题的组件确实具有如下函数调用:
{ids.map(id => GridTile({ id, record: data[id], basePath, classes, rowClick, getTileProps, resource }))}
切换为渲染可解决此问题:
{ids.map(id => <GridTile id={id} record={data[id] } basePath={basePath} classes={classes} rowClick={rowClick} getTileProps={getTileProps} resource={resource} /> )}