无法在 React useRef 中分配给只读 属性 'current'
Cannot assign to read only property 'current' in React useRef
我在功能组件中使用 React useRef
来获取 html 对象上的 link 并将其存储在 Recoil 原子中。例如:
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 ,
});
但是当我的父组件卸载时我得到错误:
react-dom.development.js:20997 Uncaught TypeError: Cannot assign to
read only property 'current' of object '#' in file
reac-dom.development.js
我想不出是什么问题;
你不能只传递一个 ref
作为 prop。
通常情况下,组件会隐藏其实现,因此父组件不应能够访问子组件创建的 DOM 元素。但是在极少数情况下,您希望在组件上允许这样做,您必须使用 forwardRef
:
明确地这样做
const Children = React.forwardRef((props, someRef) => {
// −−−−−−−−−−−−−−−−−−^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
return <input ref={someRef}/>
});
// −−^
const Parent = () => {
const someRef = useRef();
return <Children ref={someRef} />;
};
the documentation 中的更多内容。
这里的问题是默认情况下原子是冻结的(参见 documentation)并且 ref 通过改变对象的 current
属性 来工作。
您可以通过传递 dangerouslyAllowMutability: true
来防止对象冻结。
export const refLinkState = atom({
key: 'refLink',
default: null ,
dangerouslyAllowMutability: true,
});
请注意,如果 ref 本身被另一个 ref 替换,这只会更新所有订阅者。如果 ref 消费者更改 current
属性,订阅者将不会重新呈现,因为 ref 对象仍然是同一个对象。
您可以不使用 ref 来解决这个问题,而是将 ref 值直接传递到您的共享状态。
// without dangerouslyAllowMutability
export const refLinkState = atom({
key: 'refLink',
default: null ,
});
const Children = () => {
const [refLink, setRefLink] = useRecoilState(refLinkState);
return <input ref={setRefLink} />;
};
在上面的场景中,我们已经完全消除了 refs,而是将 DOM 元素存储在没有 ref 包装器的反冲状态中。
但是就像 forward refs documentation 提到的那样:
React components hide their implementation details, including their rendered output. Other components using FancyButton
usually will not need to obtain a ref to the inner button
DOM element. This is good because it prevents components from relying on each other’s DOM structure too much.
在不太了解结构和您想要实现的目标的情况下,您可以提取 Child
中的相关数据并将其存储在共享状态中。但如果我们有更多的上下文,可能会有更好的解决方案。
如果您在 TypeScript 中遇到此错误,请尝试在 类型注释 中列出 null
,这会将其从 RefObject
更改为 MutableRefObject
。帮我解决了。
来自
const myRef = useRef<MyType>(null)
到
const myRef = useRef<MyType | null>(null)
这样做之后,调用更改 current
不应导致此错误(例如 myRef.current = null
)。
我在功能组件中使用 React useRef
来获取 html 对象上的 link 并将其存储在 Recoil 原子中。例如:
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 ,
});
但是当我的父组件卸载时我得到错误:
react-dom.development.js:20997 Uncaught TypeError: Cannot assign to read only property 'current' of object '#' in file reac-dom.development.js
我想不出是什么问题;
你不能只传递一个 ref
作为 prop。
通常情况下,组件会隐藏其实现,因此父组件不应能够访问子组件创建的 DOM 元素。但是在极少数情况下,您希望在组件上允许这样做,您必须使用 forwardRef
:
const Children = React.forwardRef((props, someRef) => {
// −−−−−−−−−−−−−−−−−−^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
return <input ref={someRef}/>
});
// −−^
const Parent = () => {
const someRef = useRef();
return <Children ref={someRef} />;
};
the documentation 中的更多内容。
这里的问题是默认情况下原子是冻结的(参见 documentation)并且 ref 通过改变对象的 current
属性 来工作。
您可以通过传递 dangerouslyAllowMutability: true
来防止对象冻结。
export const refLinkState = atom({
key: 'refLink',
default: null ,
dangerouslyAllowMutability: true,
});
请注意,如果 ref 本身被另一个 ref 替换,这只会更新所有订阅者。如果 ref 消费者更改 current
属性,订阅者将不会重新呈现,因为 ref 对象仍然是同一个对象。
您可以不使用 ref 来解决这个问题,而是将 ref 值直接传递到您的共享状态。
// without dangerouslyAllowMutability
export const refLinkState = atom({
key: 'refLink',
default: null ,
});
const Children = () => {
const [refLink, setRefLink] = useRecoilState(refLinkState);
return <input ref={setRefLink} />;
};
在上面的场景中,我们已经完全消除了 refs,而是将 DOM 元素存储在没有 ref 包装器的反冲状态中。
但是就像 forward refs documentation 提到的那样:
React components hide their implementation details, including their rendered output. Other components using
FancyButton
usually will not need to obtain a ref to the innerbutton
DOM element. This is good because it prevents components from relying on each other’s DOM structure too much.
在不太了解结构和您想要实现的目标的情况下,您可以提取 Child
中的相关数据并将其存储在共享状态中。但如果我们有更多的上下文,可能会有更好的解决方案。
如果您在 TypeScript 中遇到此错误,请尝试在 类型注释 中列出 null
,这会将其从 RefObject
更改为 MutableRefObject
。帮我解决了。
来自
const myRef = useRef<MyType>(null)
到
const myRef = useRef<MyType | null>(null)
这样做之后,调用更改 current
不应导致此错误(例如 myRef.current = null
)。