如何使用 React refs 来聚焦 Redux 表单字段?

How to use React refs to focus a Redux Form field?

我正在尝试使用 React refs 在安装时聚焦 Redux-Form Field。

当我在 componentDidMount 中尝试 this.refs.title.getRenderedComponent().focus() 时,会抛出一条错误消息:

edit_fund.js:77 Uncaught TypeError: Cannot read property 'getRenderedComponent' of undefined

当我 console.log this.refs 时,它主要是一个空对象,有时将 'title' 标识为引用,但它不可靠。

我是否错误地使用了 refs?我的代码在下面供参考。

componentDidMount = () => {
  this.refs.title
  .getRenderedComponent()
  .focus();
}

...

 <Field
    id="title"
    name="title"
    component={FormInput}
    type="text"
    ref="title" withRef
 />

请尝试使用回调函数设置 ref:

ref={(input) => { this.title = input; }}

然后使用它来获取基础 DOM 节点:

ReactDOM.findDOMNode(this.title).focus();

of if DOM 输入元素包裹在另一个元素中:

ReactDOM.findDOMNode(this.title).getElementsByTagName("input")[0].focus()

根据 React 文档,使用带有字符串的引用有一些问题。请检查 docs 了解更多详情。

我使用 redux-form 和 Material UI 并且必须执行以下操作。 MaterialCheckboxFieldMaterialTextField 是我项目包装中的自定义组件 material-ui/{Checkbox,TextField}.

我将MaterialTextField转换为class组件(按照React docs中的规定)。

You may not use the ref attribute on function components because they don’t have instances.

import { findDOMNode } from "react-dom";

字段设置焦点(在render()方法内):

<Field
  component={MaterialCheckboxField}
  label="Checkbox"
  name="..."
  onClick={event => {
    if (!event.target.checked) return;
    // focus() field after grace period
    // oddity of Material UI, does not work without
    window.setTimeout(() => this.textField.focus(), 150);
  }}
/>

Material UI specific
Suggestion to allow a grace period using setTimeout() from . Consider @Lukas' comment:

"This code may throw. What would be even better is to save setTimeout() returned ID to component and on componentWillUnmount() check if the timeout is still there and clear it if so"

将获得焦点的字段(在 render() 方法中):

<Field
  component={MaterialTextField}
  label="Text field"
  name="..."
  ref={ref => {
    const node = findDOMNode(ref);
    if (node) {
      // Material UI wraps input element, 
      // use querySelector() to obtain reference to it
      // if not using MUI, querySelector() likely not needed
      this.textField = node.querySelector("input");
    }
  }}
  withRef
/>

Note
I am using Material UI 0.x, not sure if that's why React.CreateRef() didn't work for me (the recommended approach since React 16.3).