React hooks 错误:渲染的 hooks 比上次渲染时多
我曾经有一个函数组件充当页面:
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.
在我看来,
getCreditNoteList
中的
setCreditNotes(data)
导致了错误,但我不知道原因。
因此,您需要修复几个问题。首先,您应该从 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 (
<> </>
)
}
好的,我的问题是我在导入元素时遇到了 2 个问题,首先是 pycharm 巧妙地自动错误地导入了它们,其次是我根本没有导入其中一个组件。
我希望错误消息可以比“渲染的钩子比上次渲染时更多”更具体一些。
此外,我还测试了我不需要将函数体
getCreditNoteList
移动到
useEffect
内。
感谢@chitova263 花时间提供帮助。