javascript - React 中需要类似 event.target.focus() 的东西

标签 javascript reactjs event-handling focus onchange

我正在创建一个动态列表组件,每次将内容添加到列表中时,它基本上都会呈现一个新的空文本字段。该组件如下(它使用自定义 TextFieldGroup,但我认为代码不是必需的,因为没有发生任何异常情况。):

const DynamicInputList = ({ inputs, onChangeArray, label, name, errors }) => 
{
  const nonEmptyInputs = inputs.filter(input => {
    return input !== "";
  });
  const lastIndex = nonEmptyInputs.length;
  return (
    <div>
      {nonEmptyInputs.map((input, index) => {
        return (
          <Grid container spacing={16} key={index}>
            <Grid item xs={12}>
              <TextFieldGroup
                label={label}
                id={`${name}${index}`}
                name={name}
                value={input}
                onChange={e => onChangeArray(e, index)}
                errors={errors[name]}
              />
            </Grid>
          </Grid>
        );
      })}
      <Grid container spacing={16} key={lastIndex}>
        <Grid item xs={12}>
          <TextFieldGroup
            label={label}
            id={`${name}${lastIndex}`} 
            name={name}
            value={inputs[lastIndex]}
            onChange={e => onChangeArray(e, lastIndex)}
            errors={errors[name]}
          />
        </Grid>
      </Grid>
    </div>
  );
};

onChangeArray函数如下:

  onChangeArray = (e, index) => {
    const state = this.state[e.target.name];
    if (e.target.value === "") {
      state.splice(index, 1);
      this.setState({ [e.target.name]: state });
    } else {
      state.splice(index, 1, e.target.value);
      this.setState({ [e.target.name]: state });
    }
  };

一切正常,除了当空白字段被更改(开始输入)时,它会立即从任何字段中删除焦点。我正在寻找一种方法来保持对这一领域的关注,同时仍然添加下面的新领域。

提前致谢。

最佳答案

问题是您遇到以下事件序列(假设 inputs 长度为 5):

  1. React 渲染 1 个字段(键 = 5)
  2. 用户开始输入“a”
  3. 您的状态更改已触发
  4. React 渲染 2 个全新字段(key = 1 & value = 'a',key = 5)并丢弃旧字段(key = 5)

至少有两种解决方案

不要删除/触发原始字段的重新渲染

这是更清洁的解决方案。

首先,您使用 slice 直接改变 onChangeArray 中的状态,因为 that does an in-place modification 。也许这现在不会造成问题,但它是一个很大的 React 反模式,可能会产生不可预测的行为。

这是一个快速修复:

  onChangeArray = (e, index) => {
    const state = [...this.state[e.target.name]];
    if (e.target.value === "") {
      state.splice(index, 1);
      this.setState({ [e.target.name]: state });
    } else {
      state.splice(index, 1, e.target.value);
      this.setState({ [e.target.name]: state });
    }
  };

And other options

我将把实现的重做留给您,但要点是:

  1. 使用一致的key引用,这意味着迭代所有输入并跳过空的输入,而不是首先找到空的输入并将任意键设置为总数长度。当然,您仍然应该将第一个渲染为空。
  2. 您可以考虑渲染所有内容,并根据需要使用 CSS display:none 属性来实现所需的用户体验

利用inputautofocus属性

我假设您的 TextFieldGroup 使用 input 元素。您可以通过autofocus attribute到您想要关注焦点的领域。这回答了您原来的问题。

但不建议这样做,因为您仍然不必要地运行这些重新渲染周期,然后在上面打补丁。

关于javascript - React 中需要类似 event.target.focus() 的东西,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51506919/

相关文章:

javascript - template-div 克隆到相同的模板 javascript

javascript - 单击书签时意外打开新页面

javascript - 在 Vue 中,如何根据其值设置禁用复选框?

javascript - 返回哈希值时出现意外的 token { 错误

node.js - 如何在 Kotlin-React-App 中导入 Bootstrap 库

javascript - 如何将按钮单击事件传递给回调函数

javascript - 如何在 ReactJS 中创建、监听和触发自定义事件?

javascript - 在具有重叠 "circle"div 的点击处理程序中获取错误元素

javascript - 在真正的 MVC(桌面)应用程序中单例 View 有什么好处?

javascript - ReactJS 处于开发模式