useCallback 和 useMemo 是个坑,千万别使用(二)

104 阅读2分钟

前言

书接上文

如何避免使用 useCallback

避免 useCallback 的最佳方法是将函数移出组件范围。使用完全依赖于传入参数而不是范围内值的纯函数。

示例 1

上面示例的改进:

function FidgetSpinner() {
  const [spinning, setSpinning] = useState(false)


  return (
    <>
      <p>Is it spinning? {spinning}</p>
      <Spinner spinning={spinning} setSpinning={setSpinning} />
    </>
  )
}

setSpinning 是一个稳定的函数!您可以将它传递给 <Spinner> , 使用它的来切换状态:

setSpinning((spinning) => !spinning)

你可以使用一个函数来调用 React setters,该函数将当前值作为参数。

示例 2

将使用局部作用域的函数转换为独立的(可测试🤘)函数。就像使用 react-hook-form 构建表单时一样

function ComplicatedStuff() {
  const formMethods = useForm()


  const fieldValue = formMethods.watch("field")


  return (
    <>
      <p>Live current value of field: {fieldValue}</p>
      <FormRenderComponent onSubmit={onSubmit} />
    </>
  )
}

formMethods.watch 监视您的输入字段并返回其当前值。当您构建动态表单时非常有用。

onSubmit 函数:

function ComplicatedStuff() {
    const formMethods = useForm()


    const fieldValue = formMethods.watch('field')


    async function onSubmit() {
        await fetch('...', {
            method: 'POST',
            body: JSON.stringify({
                fieldValue
            })
        })
    }

你在每次按键时都完全重新渲染💩

所以这样写:

async function onSubmit(values) {
    await fetch('...', {
        method: 'POST',
        body: JSON.stringify({
            fieldValue: values.fieldValue
        })
    })
}


function ComplicatedStuff() {
    const formMethods = useForm()


    const fieldValue = formMethods.watch('field')

React-hook-form 将所有当前值传递给 onSubmit 函数。您不需要依赖组件范围!

Cough

当然,这就是这个库的工作方式,我的观点是一般原则 👉 寻找机会重构您的函数,以便它们依赖于参数而不是作用域。

然后你可以将它们移动到任何地方。灵活性 🤩(和稳定的引用)

你什么时候需要 useCallback

如果您正在编写将在许多组件中出现的库或核心功能,请记住所有内容。

像 React Query 或 useAuth 这样的库可以让你的整个应用程序意外地重新渲染。你确实想阻止这种情况。

一个回调在 3 个小组件中共享?嗯。专注于保持快速渲染而不是担心重新渲染。

PS:现在的计算机速度很快,在我使用 React 18 的实验中,需要数千个元素才能注意到性能问题

PPS:我听说 React 团队正在开发一个自动记忆引擎来为你处理这一切🤞

全文完

谢谢!

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 20 天

点击查看活动详情