With react hooks now available should I in case of functional components wrap every function passed with props with useCallback and every other props value with useMemo ?
Also having custom function inside my component dependent on any props value should I wrap it with useCallback ?
What are good practices to decide which props or const values from component wrap with this hooks ?
If this improves performance why not to do it at all times ?
Lets consider custom button where we wrap click handler and add custom logic
function ExampleCustomButton({ onClick }) {
const handleClick = useCallback(
(event) => {
if (typeof onClick === 'function') {
onClick(event);
}
// do custom stuff
},
[onClick]
);
return <Button onClick={handleClick} />;
}
Lets consider custom button where we wrap click handler and add custom logic on condition
function ExampleCustomButton({ someBool }) {
const handleClick = useCallback(
(event) => {
if (someBool) {
// do custom stuff
}
},
[someBool]
);
return <Button onClick={handleClick} />;
}
Should i in this two cases wrap my handler with useCallback ?
Similar case with use memo.
function ExampleCustomButton({ someBool }) {
const memoizedSomeBool = useMemo(() => someBool, [someBool])
const handleClick = useCallback(
(event) => {
if (memoizedSomeBool) {
// do custom stuff
}
},
[memoizedSomeBool]
);
return <Button onClick={handleClick} />;
}
In this example I even pass memoized value to useCallback .
Another case what if in the component tree many components memoize same value ? How does this impact performance ?
Not worth it, for multiple reasons:
To put all together - you'd waste more time typing all the hooks than a user would gain on having them in the application if you want to put them everywhere. The good old rule applies: Measure, then optimize .
I agree with the principles proposed by @jalooc
To give some more insight about the exhibited use cases in the OP, here is my advice:
function Component() {
const callback = useCallback(() => { dostuff }, [deps])
return <Child prop={callback} />
}
The above makes sense if Child
is a very expensive component to render. As such, it is probably exported like so:
function Child() {
...this takes significant CPU...
}
// Export as a pure component
export default React.memo(Child)
function Component({ foo }) {
// This very expensive computation will only run when it's input (foo)
// changes, allowing Component to re-render without performance issues
const bar = useMemo(() => {
... something very complicated with `foo` ...
}, [foo])
return <div>{bar}</div>
}
useCallback
) or move it outside the scope if you can. React.memo
, with the help of #2
if necessary useMemo
)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.