今天使用react的ref可能会有些混乱。 回到类组件的年代,文档中很清楚。
我们应该将引用主要用于 DOM元素:
https://reactjs.org/docs/refs-and-the-dom.html
但是今天我们与功能组件挂钩了。
并且我们正在使用useRef
挂钩。
这也给我们带来了新的模式。使用ref包含回调或我们要保留(某种状态)的任何数据,而无需重新呈现。 其强大的API,并显示在文档中:
https://reactjs.org/docs/hooks-faq.html#is-there-something-like-instance-variables
所以现在ref可以用于:
存储可变数据
种类的记忆
但是这些文档彼此矛盾。并导致许多错误和开发团队中的冲突。
医生说了两件事,这是一个问题。
那么,在这种情况下要做的“正确”的事情是什么?
const MyComponent = (props) => {
const [myMap1, _] = useState(new Map()); // 1.
const myMap2 = useMemo(()=> new Map(), []); // 2.
const myMap3 = useRef(new Map()); // 3.
...
};
答案 0 :(得分:1)
useMemo
是一项声明性 performance optimization技术。
声明性的,因为它依赖于属于特定渲染的周围范围的state或props依赖项,并自动(重新)创建备注值。我们不必告诉useMemo
这样做。
useRef
是用于存储所有值(例如,值更新与当前渲染范围无关。
useRef
没有任何依赖性,因此不会自动更改任何值。您必须通过编写ref.current = ...
手动完成此操作(DOM节点是一个例外)。
因此,您可以将useRef
视为进入命令式世界的逃生门。
// instead of
const val = useMemo(() => 42, [myDep]); // 42 stands for some complex calculation
// do this
const ref = useRef();
ref.current = 42 // assign 42 imperatively to ref somewhere in render
甚至useRef
的{{3}} useState
:
const [ref] = useState({current:null});
ref.current = "hello";
缺点:我们回到了旧的jQuery时代:-)。必须强制设置操作,这意味着更多的人工工作和可能的错误。不可变的价值操纵也比突变更具可预测性(包括其他好处)。这就是为什么React中几乎所有内容都是不可变的。
相反,在可能的情况下保持声明性(惯用法),并针对特定情况使用经过优化的预期工具是有意义的:
useState
以声明的方式表示不可变的值,触发重新渲染useMemo
用于以声明方式记录来自状态和道具的昂贵价值useRef
用于可变值或DOM节点-独立于渲染关闭范围,不需要deps
,不会触发重新渲染,需要进行更多手动操作< / li>
答案 1 :(得分:0)
钩子useRef可用于存储任何值,例如,您有一个对象,数组或映射,而您不想为每个重新渲染而重新初始化 您可以使用useRef钩子。
// this code will recreate the object in memory on each rerender
const myObj = {foo: 'foo', bar: 'bar'}
// here you have the same object in memory even after rerenders
const refObj = useRef({foo: 'foo', bar: 'bar'})
类似地,useState钩子可用于存储正常状态变量。
useMemo在某些值取决于代码中另一个变量的情况下非常有用,并且仅在变量更改时才想更改值(在将prop作为对象传递或将已记忆的对象传递给传递给上下文提供者的value prop时很有用) )。