簡體   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