直接在 render 函数中使用 React.forwardRef
Using React.forwardRef inside render function directly
直接在另一个组件的渲染函数中使用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>
);
}
如您所见,这是针对 Next.js v9 - https://github.com/zeit/next.js/issues/7915.
中的错误的临时解决方法
注意 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>
);
}
您可能会看到,在单击按钮 forwardRef
后,输入被删除并重新创建,因此它的值变为空。
不确定这对 <Link>
是否重要,但总的来说,这意味着您希望一生只 运行 一次(比如在 componentDidMount
或useEffect(...,[])
作为备选)将更频繁地发生。
因此,如果要在这种副作用和模拟警告之间做出选择,我宁愿忽略警告。或者创建自己的 <Link >
不会引起警告。
[UPD] 遗漏了一件事:在这种情况下,React 通过引用检查 forwardRef
。因此,如果您从 render
中创建 forwardRef
(因此它在引用上是相同的),它将不会被重新创建:
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>
);
}
但我仍然相信忽略警告比引入这样的解决方法更安全。
上面的代码对我来说可读性较差并且令人困惑("why ref
is not processed at all? was it intentional? why this forwardRef
is here and not in component's file?")
我同意 skyboyer 的观点,我要补充一点,可以在渲染函数之外创建 forwardRef
组件,以避免每次渲染都重新创建组件。待审核。
const TempShallow = React.forwardRef(({ child, ...props }) => React.cloneElement(child, props))
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
return (
<NextLink href={href} as={as} prefetch={prefetch} passHref {...otherProps}>
<TempShallow {...props} {...baseprops} child={child} onClick={onClick} />
</NextLink>
)
}
直接在另一个组件的渲染函数中使用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>
);
}
如您所见,这是针对 Next.js v9 - https://github.com/zeit/next.js/issues/7915.
中的错误的临时解决方法注意 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>
);
}
您可能会看到,在单击按钮 forwardRef
后,输入被删除并重新创建,因此它的值变为空。
不确定这对 <Link>
是否重要,但总的来说,这意味着您希望一生只 运行 一次(比如在 componentDidMount
或useEffect(...,[])
作为备选)将更频繁地发生。
因此,如果要在这种副作用和模拟警告之间做出选择,我宁愿忽略警告。或者创建自己的 <Link >
不会引起警告。
[UPD] 遗漏了一件事:在这种情况下,React 通过引用检查 forwardRef
。因此,如果您从 render
中创建 forwardRef
(因此它在引用上是相同的),它将不会被重新创建:
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>
);
}
但我仍然相信忽略警告比引入这样的解决方法更安全。
上面的代码对我来说可读性较差并且令人困惑("why ref
is not processed at all? was it intentional? why this forwardRef
is here and not in component's file?")
我同意 skyboyer 的观点,我要补充一点,可以在渲染函数之外创建 forwardRef
组件,以避免每次渲染都重新创建组件。待审核。
const TempShallow = React.forwardRef(({ child, ...props }) => React.cloneElement(child, props))
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
return (
<NextLink href={href} as={as} prefetch={prefetch} passHref {...otherProps}>
<TempShallow {...props} {...baseprops} child={child} onClick={onClick} />
</NextLink>
)
}