简体   繁体   English

避免在Material-UI中多次调用自动对焦 <TextField> 零件

[英]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: <Empty> component which renders the <LoginForm> with certain props 空: <Empty>组件,使用某些道具呈现<LoginForm>
  • filled: <Wrapper> component - equivalent to <Fragment> 填充: <Wrapper>组件-等效于<Fragment>

Any of the states under filled are rendered as a child of <Wrapper> . 处于filled状态的任何状态均呈现为<Wrapper>的子状态。

  • typing: <Typing> component which renders <LoginForm> with different props 类型: <Typing>组件, <LoginForm>使用不同的道具渲染<LoginForm>
  • authenticating: <Authenticating> component which renders a spinner. authenticating:呈现旋转器的<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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM