繁体   English   中英

反应钩子错误:渲染的钩子比上一次渲染时更多

[英]React hooks error: Rendered more hooks than during the previous render

我曾经有一个功能组件充当页面:

export default function NormalList(props) {
    const pageSize = 20;
    const [page, setPage] = useState(1)
    const [searchString, setSearchString] = useState(null);
    const [creditNotes, setCreditNotes] = useState(() => getCreditNoteList());
    const [ordering, setOrdering] = useState(null);

    useEffect(() => getCreditNoteList(), [page, searchString, ordering]);

    function getCreditNoteList() {
        API.fetchCreditNoteList({
            account_id: props.customerId, page, page_size: pageSize, searchString, ordering
        }).then(data => {
            setCreditNotes(data);
        });
    }
    return (<>{creditNotes.results.map(record => <...>}</>)
}

这一直运行良好,但最近我需要用ListPage组件环绕NormalList

export default function ListPage(props) {
    const customerId = props.match.params.customer_id;
    return (<div>...<div><NormalList/></div></div>)
}

然后突然间我收到这个错误Rendered more hooks than during the previous render.

在我看来,那setCreditNotes(data)getCreditNoteList导致错误,但我不知道为什么。

因此,您需要解决一些问题。 首先,您应该从 useState 函数中删除函数调用,您应该只在 useEffect 钩子中执行副作用,请参阅React Docs

接下来的事情是,每当你决定使用依赖数组到你的 useEffect 钩子时,你应该包含 useEffect 的所有依赖项,即所有的 props,状态包括你在 useEffect 钩子中使用的函数组件中的函数。 因此,经验法则永远不会对您的依赖关系撒谎! 否则你会射中自己的脚。

因此,最简单的选择是将getCreditNoteList函数移动到 useEffect 钩子中,并将 useEffect 钩子的所有依赖项添加到依赖项数组中。


export default function NormalList({ customerId }) {
    const pageSize = 20;
    const [page, setPage] = useState(1)
    const [searchString, setSearchString] = useState(null);
    const [creditNotes, setCreditNotes] = useState({});
    const [ordering, setOrdering] = useState(null);

    useEffect(() => {

      function getCreditNoteList() {
        API.fetchCreditNoteList({
            account_id: customerId, 
            page, 
            page_size: pageSize, 
            searchString, 
            ordering
        }).then(data => {
            setCreditNotes(data);
        });
      }

      getCreditNoteList(),

       // add ALL! dependencies
    }, [page, searchString, ordering, pageSize, customerId]))

    return (
       <> </>
    )
}

第二个选项如果您想在其他地方使用getCreditNoteList函数并希望将其保留在 useEffect 钩子之外,您可以通过将getCreditNoteList逻辑包装在 useCallback 钩子中来实现,如下所示,并将该函数添加到 useEffect 钩子内的依赖数组中,原因如下我之前提到过。

export default function NormalList({ customerId }) {
    const pageSize = 20;
    const [page, setPage] = useState(1)
    const [searchString, setSearchString] = useState(null);
    const [creditNotes, setCreditNotes] = useState({});
    const [ordering, setOrdering] = useState(null);

    const getCreditNoteList = useCallback(() => {
        API.fetchCreditNoteList({
            account_id: customerId, 
            page, 
            page_size: pageSize, 
            searchString, 
            ordering
        }).then(data => {
            setCreditNotes(data);
        });
     // the function only changes when any of these dependencies change
    },[page, searchString, ordering, pageSize, customerId])

    useEffect(() => {

      getCreditNoteList(),

    },[getCreditNoteList])

    return (
       <> </>
    )
}

好的,我的问题是我在导入元素时遇到了两个问题,首先是 pycharm 巧妙地自动错误地导入了它们,其次是我根本没有导入任何一个组件。

我希望错误消息可以比“比上一次渲染期间渲染更多的钩子”更具体一些。

此外,我测试了我也没必要动函数体getCreditNoteListuseEffect

感谢@chitova263 花时间提供帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM