React Hooks "useState/useEffect/useCallback" 被有条件地调用
React Hooks "useState/useEffect/useCallback" are called conditionally
请告诉我我需要在哪里放置 list.length 条件 来移除 React Hooks are called conditionally 错误 ?我试图将它包装在 useEffect 中,但在这种情况下,在第一次渲染时会返回一个空列表。 重要 在第一次渲染时返回列表的方式与下面代码中的逻辑相同。
const List = ({ list }) => {
if (list.length === 0) {
return <div>LOADING...</div>;
}
const [localList, setLocalList] = useState(list);
useEffect(() => {
setList(localList);
}, [localList]);
const handleChange = useCallback((id) => {
setLocalList((prevLocalList) =>
prevLocalList.map((item, index) => {
return index !== id ? item : { ...item, checked: !item.checked };
})
);
}, []);
return (
<>
{localList?.map((item, index) => (
<MemoRow key={index} {...item} handleChange={handleChange} />
))}
</>
);
};
渲染结果在组件末尾返回,而不是在开头。使第一个操作成为整体 return
最后的一部分:
return (
list.length === 0 ?
<div>LOADING...</div> :
<>
{localList?.map((item, index) => (
<MemoRow key={index} {...item} handleChange={handleChange} />
))}
</>
);
此外,您的组件中存在逻辑问题。当父组件传递 list
值时,您将在该组件的本地状态中复制该值。如果父组件 更改 list
的值,该组件将 re-render 但 不会更新其本地状态 。
考虑到 UI 中的术语“正在加载...”,这意味着这正是此处发生的事情。所以在 re-render 上,list.length === 0
现在是 false
,但是 localList
仍然是空的 。
作为“快速修复”,您可以随时更新 localList
list
更改:
useEffect(() => {
setLocalList(list);
}, [list, setLocalList]);
当然,如果父组件再次更改 list
,这也会 over-write 对 localList
的任何本地更改。但是由于这是 重复状态 那么在这种情况下应该发生什么并不是很清楚。也许你只能在 localList
为空时有条件地更新它:
useEffect(() => {
if (localList.length === 0) {
setLocalList(list);
}
}, [list, setLocalList, localList]);
这真的取决于你想如何处理这样的边缘情况。但最终,如果您希望这些更改反映在您的本地状态中,您将需要在 list
更改后更新 localList
。
请告诉我我需要在哪里放置 list.length 条件 来移除 React Hooks are called conditionally 错误 ?我试图将它包装在 useEffect 中,但在这种情况下,在第一次渲染时会返回一个空列表。 重要 在第一次渲染时返回列表的方式与下面代码中的逻辑相同。
const List = ({ list }) => {
if (list.length === 0) {
return <div>LOADING...</div>;
}
const [localList, setLocalList] = useState(list);
useEffect(() => {
setList(localList);
}, [localList]);
const handleChange = useCallback((id) => {
setLocalList((prevLocalList) =>
prevLocalList.map((item, index) => {
return index !== id ? item : { ...item, checked: !item.checked };
})
);
}, []);
return (
<>
{localList?.map((item, index) => (
<MemoRow key={index} {...item} handleChange={handleChange} />
))}
</>
);
};
渲染结果在组件末尾返回,而不是在开头。使第一个操作成为整体 return
最后的一部分:
return (
list.length === 0 ?
<div>LOADING...</div> :
<>
{localList?.map((item, index) => (
<MemoRow key={index} {...item} handleChange={handleChange} />
))}
</>
);
此外,您的组件中存在逻辑问题。当父组件传递 list
值时,您将在该组件的本地状态中复制该值。如果父组件 更改 list
的值,该组件将 re-render 但 不会更新其本地状态 。
考虑到 UI 中的术语“正在加载...”,这意味着这正是此处发生的事情。所以在 re-render 上,list.length === 0
现在是 false
,但是 localList
仍然是空的 。
作为“快速修复”,您可以随时更新 localList
list
更改:
useEffect(() => {
setLocalList(list);
}, [list, setLocalList]);
当然,如果父组件再次更改 list
,这也会 over-write 对 localList
的任何本地更改。但是由于这是 重复状态 那么在这种情况下应该发生什么并不是很清楚。也许你只能在 localList
为空时有条件地更新它:
useEffect(() => {
if (localList.length === 0) {
setLocalList(list);
}
}, [list, setLocalList, localList]);
这真的取决于你想如何处理这样的边缘情况。但最终,如果您希望这些更改反映在您的本地状态中,您将需要在 list
更改后更新 localList
。