简体   繁体   English

useState、UseRef 或 useMemo,我应该更喜欢哪个

[英]useState, UseRef, or useMemo, what should I prefer

I have a scenario where I need to store the output of a function throughout the component life cycle(this value should never change).我有一个场景,我需要在整个组件生命周期中存储 function 的 output(这个值永远不会改变)。

consider the example below考虑下面的例子

const UniqueIdView = () => {
    const [uniqueIdState1] = useState(() => uniqueId('prefix_'))
    const [uniqueIdState2] = useState(uniqueId('prefix_'))
    const uniqueIdRef = useRef(uniqueId('prefix_'))
    const uniqueIdMemo = useMemo(() => uniqueId('prefix_'), [])
    return (
        <div>
            {uniqueIdState1}
            {uniqueIdState2}
            {uniqueIdRef.current}
            {uniqueIdMemo}
       </div>
    )
}

which out of the 4 approaches mentioned above is ideal?上面提到的 4 种方法中哪一种是理想的?

My understanding:我的理解:

useState should be used to store values where the change in value should trigger re-render. useState应该用于存储值的变化应该触发重新渲染的值。

useMemo should be used in case I want to memoize the calculation, and memoization always has an associated cost.如果我想记住计算,应该使用useMemo ,并且 memoization 总是有相关的成本。

So, useRef in my opinion is suitable.所以,我认为useRef是合适的。

But, I then have one confusion:但是,我有一个困惑:

useRef will trigger my function again and again on every re-render while using the callback approach with useState will trigger my function only once. useRef将在每次重新渲染时一次又一次地触发我的 function,而使用带有useState的回调方法只会触发我的 function 一次。

But again, If I have to think of the cost of calling the function again and again, should I use useMemo (but in this case, the function is not complex, should we add the memorization overhead)?但是再一次,如果我必须考虑一次又一次调用 function 的成本,我应该使用useMemo (但在这种情况下,function 并不复杂,我们是否应该增加记忆开销)?

Update更新

What do I want to achieve?我想达到什么目标?

I want to create a custom hook that should return uniqueId which should not change on re-render我想创建一个自定义钩子,它应该返回在重新渲染时不应该改变的uniqueId

const UniqueId = () {
    const uniqueId = useStableUniqueId('prefix__')
    return <div>{uniqueId}<div>
}

so no matter how many time UniqueId re-renders the value should not change.所以无论 UniqueId 重新渲染多少次,该值都不应该改变。

The value passed to useRef is only the initial value, but if it's a function invokation it will actually be called each render.传递给useRef的值只是初始值,但如果它是 function 调用,它实际上会在每次渲染时调用。 Not so sure about the rest of your question.不太确定您的问题的 rest。 Each hook exists for a specific purpose.每个钩子都是为了特定目的而存在的。 Pick the one that serves your needs.选择满足您需求的那个。

I have a scenario where I need to store the output of a function throughout the component life cycle.我有一个场景,我需要在整个组件生命周期中存储 function 的 output。

To me the clear choice is the useMemo hook to memoize the result value of a possibly expensive function call.对我来说,明确的选择是使用useMemo挂钩来记忆可能昂贵的 function 调用的结果值。

It's not regularly updated so useState doesn't fit.没有定期更新,因此useState不适合。 If you decided to store it in state and ever needed to updated it, you would need an useEffect hook with dependency and recompute a new value and call the state updater function.如果您决定将其存储在 state 中并且需要对其进行更新,您将需要一个具有依赖关系的useEffect挂钩并重新计算新值并调用 state 更新程序 ZC1C425268E68385D14AB5074C17A。 This is essentially the useMemo hook.这本质上是useMemo钩子。

If you decided to store it in a React ref then you'd again need to pair that with a useEffect with a dependency to update the ref.current value to keep it updated, and this, again, essentially gets you the useMemo hook.如果您决定将其存储在 React ref 中,那么您将再次需要将其与具有依赖关系的useEffect配对,以更新ref.current值以使其保持更新,而这又一次为您提供了useMemo钩子。

Update更新

Since you are really looking to optimize a custom hook that provides a static unique id for the life of the component:由于您确实希望优化自定义钩子,该钩子为组件的生命周期提供 static 唯一 ID:

  1. Using useMemo使用useMemo

     const useUniqueId = (prefix = 'prefix_') => { return useMemo(() => uniqueId(prefix), []); };
  2. Using useState使用useState

     const useUniqueId = (prefix = 'prefix_') => { const [uniqueId] = useState(() => uniqueId(prefix)); return uniqueId; };

The short answer first: If I had to decide which mechanism to use I would go for useMemo :首先简短的回答:如果我必须决定使用哪种机制,我会 go 用于useMemo

const uniqueId = useMemo(() => getUniqueId('prefix_'), []);

It does all the things we want here: the getId function is only ever called once because the dependency array is empty, the returned value is stable, it is cost efficient.它完成了我们在这里想要的所有事情: getId function 只被调用一次,因为依赖数组为空,返回值稳定,成本效益高。 There is no magic cost associated with useMemo and it does not matter whether the calculation is heavy or lightweight. useMemo没有相关的魔法成本,计算是重还是轻量级都没有关系。 And as Drew said its succinct.正如德鲁所说的那样简洁。 A custom hook would look like this:自定义挂钩如下所示:

export const useUniqueId = () => {
  const uniqueId = useMemo(() => getUniqueId('prefix_'), []);
  return uniqueId;
}

The longer answer: Usually if you want a value that is not in any way connected to the render cycle and that will be stable during the lifetime of the component I would go for useRef .更长的答案:通常,如果您想要一个不以任何方式连接到渲染周期并且在组件的生命周期内稳定的值,我会 go 用于useRef But useRef does not support an initializer function as does useState or useMemo .但是useRef不像useState或 useMemo 那样支持初始化器useMemo I would not like to invoke getUniqueID on every render and therefore would be forced to combine it with a useEffect to initialize the ref.我不想在每个渲染上调用getUniqueID ,因此将被迫将它与useEffect结合起来以初始化 ref。 And that's really a bit cumbersome here, so I think useMemo does the job here.这在这里真的有点麻烦,所以我认为useMemo在这里完成了这项工作。

const uniqueId = useRef();
useEffect(() => { uniqueId.current = getUniqueId('prefix_') }, []);

And notice that the solution with useEffect will only provide the value after the render function has run to its completion, which will cause trouble if you need the uniqueID immediatly eg to set the HTML attribute ID on some element.请注意,使用 useEffect 的解决方案将仅在渲染 function 运行完成后提供值,如果您立即需要 uniqueID,例如在某些元素上设置 HTML 属性 ID,这将导致麻烦。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM