React useState hooks - 如果通过道具传递表单,则文本输入在键入时会失去焦点



我有一个可重用的组件<Layout />,它允许我将自定义组件传递到contentsidebar属性中。

在其中一个实例中,我将一个输入字段放入内容中,该内容是一个受控组件,并使用useState()来处理数据。

但是,每当我在输入中键入时,我发现键盘都会失去焦点。似乎整个表单都在重新渲染,我无法阻止它这样做。

当我的代码全部内联时,这很好,但是自从重构它以使用<Layout />组件以来,它产生了一些奇怪的效果。

  • 我不想使用核心 React 16.x 以外的任何额外库
  • 我尝试使用useCallback(),键,名称,ID,引用 - 都无济于事
  • 我已经将回调函数移出了范围,并根据这个答案传递了值,但问题仍然存在

import React, { useState } from 'react';
function Layout({ content: Content, sidebar: Sidebar }) {
return (
<>
<div>
<Content />
</div>
<div>
<Sidebar />
</div>
</>
);
}
function Page() {
const [value, setValue] = useState('');
return (
<>
<Layout
content={() => (
<input
value={value}
onChange={(event) => setValue(event.target.value)}
/>
)}
sidebar={() => (
<p>Lorem ipsum...</p>
)}
/>
</>
);
}
export default Page;

你的问题是你正在定义匿名函数并将它们视为 React 组件,这在许多情况下很好,但这里会导致 React 失去对这些函数中底层内容的理解。这意味着即使向输入添加 refs 或键也不会做任何事情,因为外部作用域每次只会看到一个全新的函数。

考虑一下:与其写<Content />,不如写<>{Content()}</>

这将得到相同的结果,但表明每次渲染 Layout 时,它对其属性有一个完全不同的视图,因此每次都重新渲染整个事物。由于输入正在被新的但不同的输入快速替换,因此浏览器在框中失去焦点。但它也可能导致大量其他问题。

相反,将<Content />替换为{content}并且不要传递匿名函数 - 而只是按原样传递原始 JSX,它将不再重新呈现子级。

import React, { useState } from 'react';
function Layout({ content, sidebar }) {
return (
<>
<div>
{content}
</div>
<div>
{sidebar}
</div>
</>
);
}
function Page() {
const [value, setValue] = useState('');
return (
<>
<Layout
content={(
<input
value={value}
onChange={(event) => setValue(event.target.value)}
/>
)}
sidebar={(
<p>Lorem ipsum...</p>
)}
/>
</>
);
}
export default Page;
问题是,当ContentLayout中渲染为 react 组件时,每次Page

重新渲染时,都会创建一个新的content实例和sidebar函数,因此 react 会在函数引用更改时重新挂载组件,因为函数在 react 组件内的每个渲染上都会重新创建,因此输入焦点丢失。

您可以使用contentsidebar组件作为渲染道具。渲染道具是组件用来知道要渲染的内容的函数道具。调用Layout内部的函数来渲染ContentSidebar

function Layout({ content: Content, sidebar: Sidebar }) {
return (
<>
<div>{Content()}</div>
<div>{Sidebar()}</div>
</>
);
}
function Page() {
const [value, setValue] = useState("");
return (
<>
<Layout
content={() => (
<input
value={value}
onChange={event => setValue(event.target.value)}
/>
)}
sidebar={() => <p>Lorem ipsum...</p>}
/>
</>
);
}

相关内容

  • 没有找到相关文章

最新更新