问题描述
现在有了反应钩子,我应该在功能组件的情况下用 useCallback 和其他所有带有 useMemo 的 props 值?
我的组件中还有依赖于任何道具值的自定义函数,我应该用 useCallback 包装它?
决定组件中的哪些 props 或 const 值使用此钩子包装的良好做法是什么?
如果这能提高性能,为什么不一直这样做呢?
让我们考虑自定义按钮,我们在其中包装点击处理程序并添加自定义逻辑
function ExampleCustomButton({ onClick }) {const handleClick = useCallback((事件) =>{if (typeof onClick === '函数') {点击(事件);}//做自定义的东西},[点击]);return ;}
让我们考虑自定义按钮,我们在其中包装点击处理程序并根据条件添加自定义逻辑
function ExampleCustomButton({ someBool }) {const handleClick = useCallback((事件) =>{如果(someBool){//做自定义的东西}},[someBool]);return ;}
在这两种情况下,我应该用 useCallback 包装我的处理程序吗?>
使用备忘录的类似案例.
function ExampleCustomButton({ someBool }) {const memoizedSomeBool = useMemo(() => someBool, [someBool])const handleClick = useCallback((事件) =>{如果(memoizedSomeBool){//做自定义的东西}},[memoizedSomeBool]);return ;}
在这个例子中,我什至将记忆值传递给 useCallback.
另一种情况,如果组件树中的许多组件记忆相同的值怎么办?这对性能有何影响?
不值得,原因有多种:
- 即使是官方文档也说只有在必要时才应该这样做.
- 请记住,过早的优化是万恶之源 :)
- 这让 DX(开发者体验)变得更糟:更难阅读;更难写;更难重构.
- 在处理原语(如您的示例中)时,记忆比不这样做会消耗更多的 CPU 能力.原始值没有 引用 的概念,因此没有什么可记忆的.另一方面,记忆本身(与任何其他钩子一样)确实需要一些微小的处理,没有什么是免费的.尽管它很小,但它仍然比什么都没有(与仅仅通过一个原始体相比),因此您可以使用这种方法射击自己的脚.
总而言之 - 如果您想将它们放在任何地方,那么输入所有钩子所浪费的时间比用户将它们放在应用程序中所花费的时间还要多.旧规则适用:衡量,然后优化.
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:
- Even official docs say you should do it only when necessary.
- Keep in mind that premature optimization is the root of all evil :)
- It makes DX (developer experience) far worse: it's harder to read; harder to write; harder to refactor.
- When dealing with primitives (like in your example) memoizing costs more CPU power than not doing it. A primitive value doesn't have a concept of references, so there's nothing to memoize in them. On the other hand, memoization itself (as any other hook) does require some tiny processing, nothing is for free. Even though it's tiny, it's still more than nothing (compared to just passing a primitive through), so you'd shoot your own foot with this approach.
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.
这篇关于我应该用 useCallback 还是 useMemo 包装每个道具,什么时候使用这个钩子?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!