[英]Avoiding multiple calls to autofocus in material-ui <TextField> component
This question is related to material-ui
<TextField>
component, however the solution is likely to be found in React itself. 这个问题与
material-ui
<TextField>
组件有关,但是该解决方案很可能在React本身中找到。
Imagine we're doing a simple login form. 想象我们正在做一个简单的登录表单。 The login form is represented by a state machine.
登录表单由状态机表示。
{
empty: {},
filled: { typing, authenticating }
}
I have a <LoginForm>
component which renders two <TextField>
components and a <Button>
. 我有一个
<LoginForm>
组件,该组件呈现两个<TextField>
组件和一个<Button>
。 The first <TextField>
autofocuses on mount. 第一个
<TextField>
自动聚焦于安装。 Pretty simple. 很简单
I have a parent component that manages the current state of the machine, and renders different components based on its value, as follows: 我有一个父组件来管理计算机的当前状态,并根据其值呈现不同的组件,如下所示:
<Empty>
component which renders the <LoginForm>
with certain props <Empty>
组件,使用某些道具呈现<LoginForm>
<Wrapper>
component - equivalent to <Fragment>
<Wrapper>
组件-等效于<Fragment>
Any of the states under filled
are rendered as a child of <Wrapper>
. 处于
filled
状态的任何状态均呈现为<Wrapper>
的子状态。
<Typing>
component which renders <LoginForm>
with different props <Typing>
组件, <LoginForm>
使用不同的道具渲染<LoginForm>
<Authenticating>
component which renders a spinner. <Authenticating>
组件。 empty
state transitions to filled
when one of the <TextBox>
components are no longer empty. empty
状态转换到filled
时的一个 <TextBox>
元件不再是空的。
Problem: 问题:
Imagine we start in the empty
state. 想象我们从
empty
状态开始。 It renders <Empty>
which renders <LoginForm>
which renders username <TextField>
with autofocus. 它呈现
<Empty>
,后者呈现<LoginForm>
,后者呈现具有自动聚焦的用户名<TextField>
。
We have focused on the username input and start typing. 我们专注于用户名输入并开始输入。 All is good.
一切都很好。
However imagine we started typing in the password first (ie the 2nd <TextBox>
that doesn't autofocus). 但是,假设我们首先开始输入密码(即第二个
<TextBox>
不会自动对焦)。 We start in the empty
state, write the first letter of our password, transition to filled>typing
state which seems to remount <LoginForm>
and autofocus once again to username input. 我们从
empty
状态开始, filled>typing
密码的第一个字母,过渡到filled>typing
状态,该状态似乎已重新安装<LoginForm>
并再次自动聚焦至用户名输入。 The result is that you can write the first letter for the password, and subsequent letters get added to the username input due to the re-autofocus. 结果是您可以输入密码的第一个字母,并且由于重新自动聚焦,后续的字母会添加到用户名输入中。
I figured since the markup produced by react is essentially the same (by virtue of wrapper components with no rendering of their own) that there would be no re-mounting, and thus we only get the autofocus on first mount (ie when starting in empty
). 我认为,由于react产生的标记本质上是相同的(由于包装器组件自身没有呈现),因此不会进行重新挂载,因此我们只能在第一次挂载时获得自动对焦(即,在
empty
启动时) )。
How might I resolve this? 我该如何解决?
Before (problematic code): 之前(问题代码):
const LoginMachineDelegator = () => {
const props = {
machine: init.machine,
render: {
[init.STATES.EMPTY]: Empty,
[init.STATES.FILLED]: Wrapper,
[init.STATES.TYPING]: Typing,
[init.STATES.AUTHENTICATING]: Authenticating
}
}
return <MachineDelegator {...props}/>;
}
React component tree when in empty
state: 处于
empty
状态时反应组件树:
MachineDelegator > Empty > LoginForm
React component tree when in filled>typing
state: 在
filled>typing
状态下反应组件树:
MachineDelegator > Wrapper > Typing > LoginForm
After (reconciled code): 之后(对帐代码):
const LoginMachineDelegator = () => {
const props = {
machine: init.machine,
[init.STATES.EMPTY]: { func: createEmptyLoginForm },
[init.STATES.FILLED]: { /* no element */ },
[init.STATES.TYPING]: { func: createTypingLoginForm },
[init.STATES.AUTHENTICATING]: { component: Authentication }
}
}
Because the functions return a react element, they themselves do not get inserted into the React component tree. 因为函数返回了react元素,所以它们本身不会插入到React组件树中。 Instead the returning element is.
相反,返回元素是。 As such, the new component tree would look like this:
这样,新的组件树将如下所示:
When in empty
state: 处于
empty
状态时:
MachineDelegator > LoginForm
When in filled>typing
state: 处于
filled>typing
状态时:
MachineDelegator > LoginForm
This ensures that the LoginForm does not get re-mounted and re-rendered 这样可以确保LoginForm不会重新挂载和重新呈现
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.