如何对自定义的React Hook 实现记忆化

20
const useSomeHook = ({number}) => {
  const [newNumber, setNewNumber] = useState(0)

  useEffect(() => {
    setNewNumber(number + 1)
  }, [number])
}

const SomeComponent = ({number, value, ...restProps}) => {

  useSomeHook({number})


  return <div>{number}</div>
}

假设我有这样的情况。每次当SomeComponent传入新的属性时,它都会调用我的useSomeHook Hook,但我想要防止这种情况发生。我只想在number改变时(memoize它)才调用它。在其他情况下,请不要触碰它。但是我没有找到任何解决这个问题的方法。你能帮我解决这个问题吗?


1
useSomeHook 中的 useEffect 钩子只有在依赖项 number 改变时才会被调用。 - sdgluck
1
所以我不明白在这种情况下记忆化能给你带来什么好处。 - sdgluck
在这种情况下还好,但是想象一下,如果我在这个钩子中有一些复杂的逻辑,并且每次使用redux表单输入内容时都会调用它,那么它将变得非常糟糕。 - Andrey Radkevich
你在 useEffect 的第二个参数中传递的内容将会触发后续调用你作为第一个参数传递的回调函数。 为了解决你的问题,你可以做两件事:1. 将深度相等性检查添加为第二个参数(这需要一些工作),和/或2. 在回调函数中添加条件;例如:if (obj.a !== obj.b) callback() - Amir
使用 useRef 替代 useState - Khaled Osman
2个回答

11

无法阻止调用 hook,否则会导致不变式违规错误。组件中的每个 hook 应在每次渲染时都执行。您应该依赖于 useEffect 的依赖参数,仅在值更改时运行条件代码。


2

使用useRef代替useState来记忆/缓存返回值,以便在跨组件使用或存在多个该组件实例时不会重新计算。

const useSomeHook = ({number}) => {
  const numberRef = useRef(0)

  useEffect(() => {
    numberRef.current = numberRef.current + 1
  }, [number])
}

const SomeComponent = ({number, value, ...restProps}) => {

  useSomeHook({number})


  return <div>{number}</div>
}

听起来你想要使用useMemo而不是useEffect

const useSomeHook = ({number}) => {
  const numberRef = useRef(0)

  cachedValue = useMemo(() => {
    return numberRef.current + 1
  }, [number])
   return cachedValue
}

const SomeComponent = ({number, value, ...restProps}) => {

  const cachedValue = useSomeHook({number})


  return <div>{number}</div>
}

如果我们的 useSomeHook 在进行 API 调用,那么使用 useRef 可能也不是一个好主意,你有什么想法? - Prateek
@Prateek 为什么不呢?我会争辩说,在进行 API 调用时使用 useRef 更好,因为你可以使用它来缓存 API 调用的响应。否则,如果你在多个组件中使用相同的 hook,就会进行多次 API 调用。 - Khaled Osman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接