reactjs 无法指派给React useRef中的只读属性'current'

2nbm6dog  于 2022-11-04  发布在  React
关注(0)|答案(3)|浏览(317)

我在功能组件中使用react useRef获取html对象上的链接,并将其存储在Recoil atom中。例如:

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 ,
});

但是,当我的父组件卸载时,我得到错误:
js:20997未捕获的类型错误:无法指派给reac-dom.development.js档案中对象'#'的只读属性'current'

我想象不出有什么问题;

abithluo

abithluo1#

如果您在TypeScript中遇到此错误,请尝试在type注解中列出null,这会将此错误从RefObject更改为MutableRefObject
起始日期

const myRef = useRef<MyType>(null)

结束日期

const myRef = useRef<MyType | null>(null)

执行此操作后,调用更改current不应导致此错误(例如,myRef.current = null)。
Source

gab6jxml

gab6jxml2#

这里的问题是,原子在默认情况下是冻结的(请参见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} />;
};

在上面的场景中,我们已经完全消除了ref,而是在没有ref Package 器的情况下以反冲状态存储DOM元素。
然而,就像forward refs documentation提到的:
React组件隐藏了它们的实现细节,包括它们呈现的输出。其他使用FancyButton**的组件通常不需要将obtain a ref**到内部的button DOM元素。这很好,因为它防止了组件过于依赖彼此的DOM结构。
在不太了解结构和具体目标的情况下,您可以提取Child中的相关数据,并将其存储在共享状态中。

t5zmwmid

t5zmwmid3#

你不能把一个ref当作道具来传递。
通常情况下,组件会隐藏它的实现,这样父组件就不能访问由子组件创建的DOM元素。但是在极少数情况下,如果你想允许组件这样做,你必须使用forwardRef显式地这样做:

const Children = React.forwardRef((props, someRef) => {
// −−−−−−−−−−−−−−−−−−^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      return <input ref={someRef}/>
    });
// −−^
    const Parent = () => {
      const someRef = useRef();
      return <Children ref={someRef} />;
    };

the documentation中的更多内容。

相关问题