直接在渲染函数中使用 React.forwardRef

Kos*_*ika 3 javascript reactjs next.js

React.forwardRef直接在另一个组件的渲染函数中使用方法是否安全-

例子 -

function Link() {
  // --- SOME EXTENSIVE LOGIC AND PROPS CREATING GOES HERE ---
  // --- OMITTED FOR SIMPLICITY ---

  // TO DO: Remove forward ref as soon Next.js bug will be fixed -
  // https://github.com/zeit/next.js/issues/7915

  // Please note that Next.js Link component uses ref only to prefetch link
  // based on its availability in view via IntersectionObserver API -
  // https://github.com/zeit/next.js/blob/canary/packages/next/client/link.tsx#L119
  const TempShallow = React.forwardRef(props =>
    cloneElement(child, {
      ...props,
      ...baseProps,
      onClick: handleClick
    })
  );

  return (
    <NextLink href={href} as={as} prefetch={prefetch} passHref {...otherProps}>
      <TempShallow />
    </NextLink>
  );
}
Run Code Online (Sandbox Code Playgroud)

如您所见,这是 Next.js v9 - https://github.com/zeit/next.js/issues/7915 中错误的临时解决方法。

sky*_*yer 9

当心forwardRef影响协调:元素总是在父重新渲染时重新创建。

function App() {
  const [,setState] = useState(null);
  const Input = React.forwardRef((props, ref) => <input {...props} />)
  return (
    <div className="App">
      <h1>Input something into inputs and then click button causing re-rendering</h1>
      <Input placeholder="forwardRef" />
      <input placeholder="native" />
      <button onClick={setState}>change state to re-render</button>
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

您可能会看到,在单击 button forwardRef-ed 后,输入被删除并重新创建,因此它的值变为空。

不确定这是否重要,<Link>但总的来说,这意味着您希望每个生命周期只运行一次的事情(例如获取数据componentDidMountuseEffect(...,[])作为替代方案)将更频繁地发生。

因此,如果在此副作用和模拟警告之间进行选择,我宁愿忽略警告。或者创建自己的<Link >不会引起警告的。

[UPD] 错过了一件事:forwardRef在这种情况下,React通过引用检查。因此,如果您使用forwardRefrender(因此参考上相同),它将不会被重新创建:

const Input = React.forwardRef((props, ref) => <input {...props} />)

function App() {
  const [,setState] = useState(null);
  return (
    <div className="App">
      <h1>Input something into inputs and then click button causing re-rendering</h1>
      <Input placeholder="forwardRef" />
      <input placeholder="native" />
      <button onClick={setState}>change state to re-render</button>
    </div>
  );
}

Run Code Online (Sandbox Code Playgroud)

但我仍然相信忽略警告比引入这样的解决方法更安全。

上面的代码对我来说可读性较差并且令人困惑(“为什么ref根本没有处理?这forwardRef是故意的?为什么这是在这里而不是在组件文件中?”)