useState、UseRef 或 useMemo,我更喜欢哪个
useState, UseRef, or useMemo, what should I prefer
我有一个场景,我需要在整个组件生命周期中存储函数的输出(这个值永远不会改变)。
考虑下面的例子
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>
)
}
上述 4 种方法中哪一种是理想的?
我的理解:
useState
应用于存储值,其中值的更改应触发重新渲染。
useMemo
应该在我想记忆计算的情况下使用,记忆总是有相关的成本。
所以,useRef
在我看来是合适的。
但是,我有一个困惑:
useRef
将在每次重新渲染时一次又一次地触发我的函数,而使用 useState
的回调方法只会触发我的函数一次。
但是再一次,如果我不得不考虑一次又一次调用函数的成本,我是否应该使用useMemo
(但是在这种情况下,函数并不复杂,我们是否应该增加记忆开销)?
更新
我想达到什么目标?
我想创建一个自定义挂钩,它应该 return uniqueId
在重新渲染时不应该改变
const UniqueId = () {
const uniqueId = useStableUniqueId('prefix__')
return <div>{uniqueId}<div>
}
因此无论 UniqueId 重新呈现多少次,该值都不应更改。
传递给useRef
的值只是初始值,但如果是函数调用,它实际上会在每次渲染时被调用。不太确定你的问题的其余部分。每个挂钩都有特定的用途。选择满足您需求的那个。
I have a scenario where I need to store the output of a function
throughout the component life cycle.
对我来说,明确的选择是 useMemo
钩子来记忆 可能 昂贵的函数调用的结果值。
它不是定期更新所以useState
不适合。如果您决定将它存储在状态中并且需要更新它,您将需要一个 useEffect
具有依赖性的挂钩并重新计算一个新值并调用状态更新程序函数。这本质上是 useMemo
钩子。
如果您决定将其存储在 React ref 中,那么您将再次需要将其与 useEffect
配对并具有依赖性以更新 ref.current
值以使其保持更新,而这,再一次,本质上让你得到 useMemo
钩子。
更新
由于您确实希望优化为组件的生命周期提供静态唯一 ID 的自定义挂钩:
使用useMemo
const useUniqueId = (prefix = 'prefix_') => {
return useMemo(() => uniqueId(prefix), []);
};
使用useState
const useUniqueId = (prefix = 'prefix_') => {
const [uniqueId] = useState(() => uniqueId(prefix));
return uniqueId;
};
首先是简短的回答:如果我必须决定使用哪种机制,我会选择 useMemo
:
const uniqueId = useMemo(() => getUniqueId('prefix_'), []);
它在这里做了我们想要的所有事情:getId
函数只被调用一次,因为依赖数组是空的,返回值是稳定的,它是成本高效的。没有与 useMemo
相关的神奇成本,计算是重还是轻都无关紧要。正如德鲁所说,它简洁明了。
自定义挂钩如下所示:
export const useUniqueId = () => {
const uniqueId = useMemo(() => getUniqueId('prefix_'), []);
return uniqueId;
}
较长的答案:
通常,如果您想要一个与渲染周期没有任何关系并且在组件的生命周期内保持稳定的值,我会选择 useRef
。
但是 useRef
不像 useState
或 useMemo
那样支持初始化函数。我不想在每个渲染器上调用 getUniqueID
,因此将被迫将它与 useEffect
结合起来以初始化 ref。这在这里确实有点麻烦,所以我认为 useMemo
在这里完成了工作。
const uniqueId = useRef();
useEffect(() => { uniqueId.current = getUniqueId('prefix_') }, []);
请注意,使用 useEffect 的解决方案只会在渲染函数 运行 完成后提供值,如果您立即需要 uniqueID,这会造成麻烦,例如在某些元素上设置 HTML 属性 ID。
我有一个场景,我需要在整个组件生命周期中存储函数的输出(这个值永远不会改变)。
考虑下面的例子
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>
)
}
上述 4 种方法中哪一种是理想的?
我的理解:
useState
应用于存储值,其中值的更改应触发重新渲染。
useMemo
应该在我想记忆计算的情况下使用,记忆总是有相关的成本。
所以,useRef
在我看来是合适的。
但是,我有一个困惑:
useRef
将在每次重新渲染时一次又一次地触发我的函数,而使用 useState
的回调方法只会触发我的函数一次。
但是再一次,如果我不得不考虑一次又一次调用函数的成本,我是否应该使用useMemo
(但是在这种情况下,函数并不复杂,我们是否应该增加记忆开销)?
更新
我想达到什么目标?
我想创建一个自定义挂钩,它应该 return uniqueId
在重新渲染时不应该改变
const UniqueId = () {
const uniqueId = useStableUniqueId('prefix__')
return <div>{uniqueId}<div>
}
因此无论 UniqueId 重新呈现多少次,该值都不应更改。
传递给useRef
的值只是初始值,但如果是函数调用,它实际上会在每次渲染时被调用。不太确定你的问题的其余部分。每个挂钩都有特定的用途。选择满足您需求的那个。
I have a scenario where I need to store the output of a function throughout the component life cycle.
对我来说,明确的选择是 useMemo
钩子来记忆 可能 昂贵的函数调用的结果值。
它不是定期更新所以useState
不适合。如果您决定将它存储在状态中并且需要更新它,您将需要一个 useEffect
具有依赖性的挂钩并重新计算一个新值并调用状态更新程序函数。这本质上是 useMemo
钩子。
如果您决定将其存储在 React ref 中,那么您将再次需要将其与 useEffect
配对并具有依赖性以更新 ref.current
值以使其保持更新,而这,再一次,本质上让你得到 useMemo
钩子。
更新
由于您确实希望优化为组件的生命周期提供静态唯一 ID 的自定义挂钩:
使用
useMemo
const useUniqueId = (prefix = 'prefix_') => { return useMemo(() => uniqueId(prefix), []); };
使用
useState
const useUniqueId = (prefix = 'prefix_') => { const [uniqueId] = useState(() => uniqueId(prefix)); return uniqueId; };
首先是简短的回答:如果我必须决定使用哪种机制,我会选择 useMemo
:
const uniqueId = useMemo(() => getUniqueId('prefix_'), []);
它在这里做了我们想要的所有事情:getId
函数只被调用一次,因为依赖数组是空的,返回值是稳定的,它是成本高效的。没有与 useMemo
相关的神奇成本,计算是重还是轻都无关紧要。正如德鲁所说,它简洁明了。
自定义挂钩如下所示:
export const useUniqueId = () => {
const uniqueId = useMemo(() => getUniqueId('prefix_'), []);
return uniqueId;
}
较长的答案:
通常,如果您想要一个与渲染周期没有任何关系并且在组件的生命周期内保持稳定的值,我会选择 useRef
。
但是 useRef
不像 useState
或 useMemo
那样支持初始化函数。我不想在每个渲染器上调用 getUniqueID
,因此将被迫将它与 useEffect
结合起来以初始化 ref。这在这里确实有点麻烦,所以我认为 useMemo
在这里完成了工作。
const uniqueId = useRef();
useEffect(() => { uniqueId.current = getUniqueId('prefix_') }, []);
请注意,使用 useEffect 的解决方案只会在渲染函数 运行 完成后提供值,如果您立即需要 uniqueID,这会造成麻烦,例如在某些元素上设置 HTML 属性 ID。