无法在 React useRef 中分配给只读属性“current”

den*_*oid 22 javascript reactjs use-ref recoiljs

useRef在功能组件中使用了 React 来获取 html 对象上的链接并将其存储在 Recoilatom 中。例如:

const Children = () => {
  const [refLink, setSrefLink] = useRecoilState(refLink)
  return <input ref={someRef}/>
}
const Parent = () => {
  const [refLink, setSrefLink] = useRecoilState(refLink)
  const someRef = useRef();
  setSomeRef(someRef)
  return <Children />;
}

export const refLink = atom({
    key: 'refLink',
    default: null ,
});
Run Code Online (Sandbox Code Playgroud)

但是当我的父组件卸载时我收到错误:

react-dom.development.js:20997未捕获类型错误:无法分配给文件reac-dom.development.js中对象“#”的只读属性“当前”

在此输入图像描述

我无法想象有什么问题;

Nel*_*elu 40

如果您在 TypeScript 中遇到此错误,请尝试null类型注释中列出,这会将其从 a 更改RefObject为 a MutableRefObject

const myRef = useRef<MyType>(null)
Run Code Online (Sandbox Code Playgroud)

const myRef = useRef<MyType | null>(null)
Run Code Online (Sandbox Code Playgroud)

这样做后,重新分配current不应导致此错误(例如myRef.current = null)。

来源


3li*_*t0r 6

这里的问题是原子默认被冻结(请参阅文档),并且 ref 通过改变current对象的属性来工作。

\n

您可以通过传递来防止对象冻结dangerouslyAllowMutability: true

\n
export const refLinkState = atom({\n    key: \'refLink\',\n    default: null ,\n    dangerouslyAllowMutability: true,\n});\n
Run Code Online (Sandbox Code Playgroud)\n

请注意,如果引用本身被另一个引用替换,这只会更新所有订阅者。如果 ref 消费者更改了current属性,订阅者将不会重新渲染,因为 ref 对象仍然是同一个对象。

\n

您可以通过不使用 ref 而是将 ref 值直接传递到共享状态来解决此问题。

\n
// without dangerouslyAllowMutability\nexport const refLinkState = atom({\n    key: \'refLink\',\n    default: null ,\n});\n\nconst Children = () => {\n  const [refLink, setRefLink] = useRecoilState(refLinkState);\n  return <input ref={setRefLink} />;\n};\n
Run Code Online (Sandbox Code Playgroud)\n

在上面的场景中,我们完全消除了 refs,而是在没有 ref 包装器的情况下将 DOM 元素存储在反冲状态。

\n

然而,就像前向参考文档提到的那样:

\n
\n

React 组件隐藏其实现细节,包括渲染的输出。其他使用的组件FancyButton 通常不需要 获取内部DOM 元素的引用button。这很好,因为它可以防止组件过度依赖彼此\xe2\x80\x99s DOM 结构。

\n
\n

例如,在不了解结构以及您到底想要实现什么的情况下,您可以提取相关数据并将Child其存储在共享状态中。但如果我们有更多的背景,可能会有更好的解决方案。

\n