避免在Material-UI <textfield>组件中多次调用自动对焦功能

时间:2018-09-11 10:24:46

标签: javascript reactjs material-ui

这个问题与material-ui <TextField>组件有关,但是解决方案很可能在React本身中找到。

想象一下我们正在做一个简单的登录表单。登录表单由状态机表示。

{
  empty: {},
  filled: { typing, authenticating }
}

我有一个<LoginForm>组件,它呈现了两个<TextField>组件和一个<Button>。第一个<TextField>会自动对焦于安装座。很简单。

我有一个父组件来管理机器的当前状态,并根据其值呈现不同的组件,如下所示:

  • 空:<Empty>组件,用于通过特定道具渲染<LoginForm>
  • 已填充:<Wrapper>个组件-等效于<Fragment>

filled下的任何状态都呈现为<Wrapper>的子级。

  • 键入:<Typing>组件,它使用不同的道具渲染<LoginForm>
  • 验证:<Authenticating>组件,用于呈现微调器。
empty组件中的一个不再为空时,

filled的状态转换为<TextBox>


问题:

想象一下,我们从empty状态开始。它会渲染<Empty>,后者会渲染<LoginForm>,后者会使用自动对焦来渲染用户名<TextField>

我们专注于用户名输入并开始输入。一切都很好。

但是,假设我们首先开始输入密码(即第二个<TextBox>不会自动对焦)。我们从empty状态开始,输入密码的第一个字母,然后过渡到filled>typing状态,该状态似乎已重新安装<LoginForm>并再次自动聚焦于用户名输入。结果是您可以输入密码的第一个字母,并且由于重新自动聚焦,后续的字母会添加到用户名输入中。

我认为,由于react产生的标记本质上是相同的(由于包装器组件本身没有呈现),因此不会进行重新挂载,因此我们只能在第一次挂载时获得自动聚焦(即从empty开始。

我该如何解决?

1 个答案:

答案 0 :(得分:0)

之前(问题代码):

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}/>;
}

处于empty状态的反应组件树:

MachineDelegator > Empty > LoginForm

处于filled>typing状态的反应组件树:

MachineDelegator > Wrapper > Typing > LoginForm


之后(对帐代码):

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 }
  }
}

由于函数返回了react元素,因此它们本身不会插入React组件树中。相反,返回元素是。这样,新的组件树将如下所示:

处于empty状态时:

MachineDelegator > LoginForm

处于filled>typing状态时:

MachineDelegator > LoginForm


这确保LoginForm不会被重新挂载和重新呈现