出现错误:渲染的钩子比预期的少。使用useState时

时间:2020-06-17 13:52:46

标签: javascript reactjs

我正在使用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>
);

有什么主意我为什么会出现此错误?

谢谢。

1 个答案:

答案 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} /> )}