将useState
钩子的setter函数用作回调ref函数是否安全?这会给Suspense或其他即将发生的React变化带来麻烦吗?如果“是,可以”,那太酷了!如果“不”,为什么不呢?如果“也许”,那么什么时候可以还是不可以?
我之所以问是因为我的一个组件在调用DOM API之前需要安装三个引用。这些必需的引用中有两个是通过JSX ref
属性在同一组件中分配的“常规”引用。稍后,将通过React上下文在深度嵌套的组件中分配另一个ref。我需要一种方法来在所有三个引用都安装后强制重新渲染父组件,并在卸载任何引用时强制进行useEffect
清理。
最初,我编写了自己的回调引用处理程序,该处理程序称为useState
setter,我将其存储在上下文提供程序中。但是后来我意识到useState
设置器完成了我自己的回调引用所做的一切。使用setter而不是编写自己的回调ref函数是否安全?还是有一种更好和/或更安全的方式来做我想做的事情?
我尝试使用Google搜索"useState" "callback ref"
(以及其他类似的关键字变体),但结果没有帮助,除了@theKashey出色的use-callback-ref软件包之外,我肯定会在其他地方使用它(例如当我需要将回调ref传递给需要RefObject的组件时,或者当我既需要回调又需要在本地使用ref时),但是在这种情况下,当ref更改时,所有回调需要做的就是设置状态变量,所以安东的包裹似乎在这里太过分了。
下面是一个简化的示例,位于https://codesandbox.io/s/dreamy-shockley-5dc74。
import * as React from 'react';
import { useState, forwardRef, useEffect, createContext, useContext, useMemo } from 'react';
import { render } from 'react-dom';
const Child = forwardRef((props, ref) => {
return <div ref={ref}>This is a regular child component</div>;
});
const refContext = createContext();
const ContextUsingChild = props => {
const { setValue } = useContext(refContext);
return <div ref={setValue}>This child uses context</div>;
};
const Parent = () => {
const [child1, setChild1] = useState(null);
const [child2, setChild2] = useState(null);
const [child3, setChild3] = useState(null);
useEffect(() => {
if (child1 && child2) {
console.log(`Child 1 text: ${child1.innerText}`);
console.log(`Child 2 text: ${child2.innerText}`);
console.log(`Child 3 text: ${child3.innerText}`);
} else {
console.log(`Child 1: ${child1 ? '' : 'not '}mounted`);
console.log(`Child 2: ${child2 ? '' : 'not '}mounted`);
console.log(`Child 3: ${child3 ? '' : 'not '}mounted`);
console.log(`In a real app, would run a cleanup function here`);
}
}, [child1, child2, child3]);
const value = useMemo(() => ({ setValue: setChild3 }), []);
return (
<refContext.Provider value={value}>
<div className="App">
This is text in the parent component
<Child ref={setChild1} />
<Child ref={setChild2} />
<ContextUsingChild />
</div>
</refContext.Provider>
);
};
const rootElement = document.getElementById('root');
render(<Parent />, rootElement);
答案 0 :(得分:-1)
useState
“setter” 函数在渲染周期内保持相同的引用,所以这些应该可以安全使用。甚至 mentioned 可以在依赖数组中省略它们:
(setCount 函数的身份保证是稳定的,所以省略是安全的。)
你可以直接传递setter函数:
<refContext.Provider value={setChild3}>
...然后阅读:
const ContextUsingChild = props => {
const setChild3 = useContext(refContext);
return <div ref={setChild3}>This child uses context</div>;
};