英文:
Do I need useCallback when running a function from a child component
问题
Should the hoc function handleDoIt()
be wrapped in useCallback here?
const handleDoItCallback = useCallback(async () => {
setStatus("Doing It...");
await onDoIt();
handleDidIt();
}, [onDoIt]);
英文:
I understand that we should consider useCallback
when we care about ensuring referential equality is considered during parent component renders. However, I am not clear if I need it in the following scenario where the parent is actually processing a child function.
import { ReactNode, useCallback, useState } from "react";
interface WrapperProps {
children: ReactNode;
onDoIt: () => Promise<void>;
}
type Status = "Do It" | "Doing It..." | "Did It";
export const Wrapper: React.FC<WrapperProps> = ({ children, onDoIt }) => {
const [status, setStatus] = useState<Status>("Do It");
const handleDidIt = () => {
setStatus("Did It");
};
const handleDoIt = async () => {
setStatus("Doing It...");
await onDoIt();
handleDidIt();
};
return (
<>
<button onClick={handleDoIt} disabled={status !== "Do It"}>
{status}
</button>
<hr />
{children}
</>
);
};
export default function App() {
const [result, setResult] = useState<string>("");
const doIt = (): Promise<void> => {
return new Promise((resolve) => {
window.setTimeout(() => {
setResult("Done, thanks");
return resolve();
}, 1000);
});
};
return (
<Wrapper onDoIt={doIt}>
<h1>Hello CodeSandbox</h1>
<p>{result}</p>
</Wrapper>
);
}
Should the hoc function handleDoIt()
be wrapped in useCallback here?
const handleDoItCallback = useCallback(async () => {
setStatus("Doing It...");
await onDoIt();
handleDidIt();
}, [onDoIt]);
答案1
得分: -1
是的,它应该被包含在依赖项中,以及它使用的任何其他函数。
在这种情况下:
const handleDidIt = useCallback(() => {
setStatus("Did It");
}, []);
然后在依赖项数组中包括:
const handleDoIt = useCallback(async () => {
setStatus("Doing It...");
await onDoIt();
handleDidIt();
}, [onDoIt, handleDidIt]);
如果不这样做,那么handleDoIt
可能会与最新的handleDidIt
不一致。在这种情况下,这并不重要,因为它只是一个常量状态更新,但在更复杂的逻辑中可能会有影响。
最后,在父组件中:
const doIt = useCallback((): Promise<void> => {
return new Promise((resolve) => {
window.setTimeout(() => {
setResult("Done, thanks");
return resolve();
}, 1000);
});
});
值得注意的是,setStatus
不需要包含在任何依赖数组中,因为它始终保持稳定。
英文:
Yes it should be wrapped, as well as any other function it uses.
In this case:
const handleDidIt = useCallback(() => {
setStatus("Did It");
}, []);
and then include in the deps array:
const handleDoIt = useCallback(async () => {
setStatus("Doing It...");
await onDoIt();
handleDidIt();
}, [onDoIt, handleDidIt]);
If you do not do this, then handleDoIt
can fall out-of-date with the latest handleDidIt
. In this case, it doesn't matter as it's just a constant state update, but it can with more complex logic.
Lastly, in the parent:
const doIt = useCallback((): Promise<void> => {
return new Promise((resolve) => {
window.setTimeout(() => {
setResult("Done, thanks");
return resolve();
}, 1000);
});
});
Notably, setStatus
does not need to be included in either dependency array because it is always guaranteed to be stable.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论