我们都知道如何使用 React.useCallback 和 React.useMemo,但有时我们会很困惑应该选择哪一个。
这里我将通过一些案例来帮助大家了解在某些特定情况下我们应该使用什么钩子函数。
import React, { useState } from 'react' export default function App() { const [num1, setNum1] = useState(10) const [num2, setNum2] = useState(12) return <div>{num1 + num2}</div> }
在上面的简单示例中,我们可以在 HTML 元素部分通过 num1 + num2 求和,但如果我们有一些更复杂的计算逻辑,我们不应该再这样做了。
import React, { useState, useMemo } from 'react' export default function App() { const [num1, setNum1] = useState(10) const [num2, setNum2] = useState(12) const sum = useMemo(() => { const _num1 = Number(num1), _num2 = Number(num2) if (Number.isNaN(_num1) || Number.isNaN(_num2)) { return "check your num's type" } return _num1 + _num2 }, [num1, num2]) return <div>{sum}</div> }
在这个示例代码块中,我们选择 useMemo 来保留 num1 + num2 的结果值,但我们添加了一些类型检查逻辑,因为我们不能完全相信 num1 或 num2 的类型将是数字,所以当类型出错时,我们将显示占位符文本。
在这种情况下,你无法在HTML部分用一行简单的代码实现这种效果。当然,你可以在HTML部分用条件运算符编写一些逻辑代码(JSX允许你这样做),但代价是牺牲代码的可读性。
因此,useMemo 是处理这种情况的不错选择。
好吧,让我们来讨论一个更复杂的案例。
import React, { useState, useMemo } from 'react' export default function App() { const [num1, setNum1] = useState(10) const [num2, setNum2] = useState(12) const [num3, setNum3] = useState(100) const [num4, setNum4] = useState(120) const sum1 = useMemo(() => { const _num1 = Number(num1), _num2 = Number(num2) if (Number.isNaN(_num1) || Number.isNaN(_num2)) { return "check your num's type" } return _num1 + _num2 }, [num1, num2]) return ( <> <div>{sum1}</div> <div>{num3 + num4}</div> </> ) }
如你所见,我们这里有 num3 和 num4 来渲染它们的总和。如果我们还想复用num1 + num2的逻辑,该怎么办呢?当然,我们仍然可以使用 useMemo 来定义一个 sum2,但是重用逻辑来验证 num 的类型并不是一个好主意。因此我们需要将验证逻辑从 useMemo 中分离出来。然后 useCallback 出现了!
import React, { useState, useCallback } from 'react' const validteNumAndSum = (number1, number2) => { const _num1 = Number(number1), _num2 = Number(number2) if (Number.isNaN(_num1) || Number.isNaN(_num2)) { return "check your num's type" } return _num1 + _num2 } export default function App() { const [num1, setNum1] = useState(10) const [num2, setNum2] = useState(12) const [num3, setNum3] = useState(100) const [num4, setNum4] = useState(120) const sumFunc = useCallback(validteNumAndSum, []) return ( <> <div>{sumFunc(num1, num2)}</div> <div>{sumFunc(num3, num4)}</div> </> ) }
如你所见,我们使用useCallback返回一个新函数,其逻辑是验证num的类型并计算总和,并且我们可以轻松地在HTML部分重用这个validteNumAndSum函数。
好的,让我们进入结论部分:
如果你可以轻松地进行计算(数学或更复杂的情况),则不需要 useMemo 和 useCallback。
如果你的计算逻辑比较复杂,只需要计算一次,你可以选择useMemo钩子来封装你的计算过程并返回一个简单的结果。
但是如果您多次使用相同的逻辑,您可以选择 useCallback 返回一个记忆的函数,以便在您的组件中重用它。
对于 useCallback 的情况我感到非常抱歉。我犯了一个错误,那就是解释何时选择 useCallback 并创建了一个错误的示例案例。
这里我再试一次。
import React, { useState, useCallback } from 'react' export default function App() { const [base, setBase] = useState(0) const [num1, setNum1] = useState(10) const [num2, setNum2] = useState(12) const [num3, setNum3] = useState(100) const [num4, setNum4] = useState(120) const sumFunc = useCallback( (number1, number2) => { const _num1 = Number(number1), _num2 = Number(number2) if (Number.isNaN(_num1) || Number.isNaN(_num2)) { return "check your num's type" } return _num1 + _num2 + base }, [base], ) return ( <> <input type="number" value={base} onChange={e => { setBase(Number(e.target.value)) }} /> <div>{sumFunc(num1, num2)}</div> <div>{sumFunc(num3, num4)}</div> </> ) }
在上面的代码中,我们添加一个基数作为另一个变量数据,并且每个和都应该与基值相加,并且我们有一个输入来更改基值,因此每次更改基数时,sumFunc都会也可以修改,我们可以用它来计算正确的结果。
所以我会更新我关于useCallback的结论:如果我们只是需要重用一些逻辑,我们可以将这个逻辑封装成一个函数,甚至将它作为一个util函数从组件中分离出来,以便在任何地方重用它。而如果我们的逻辑仍然依赖于组件的某些变量,我们可以使用 useCallback 来封装逻辑并返回一个记忆的新函数。
以上是useCallback VS useMemo的详细内容。更多信息请关注PHP中文网其他相关文章!