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

Posted

技术标签:

【中文标题】如何使用 React refs 来聚焦 Redux Form 字段?【英文标题】:How to use React refs to focus a Redux Form field? 【发布时间】:2017-07-16 11:57:57 【问题描述】:

我正在尝试使用 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' 标识为 ref,但它并不可靠。

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

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

...

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

【问题讨论】:

这很奇怪,你的代码看起来很好,请显示整个组件代码 你解决了吗? 不,很遗憾从未解决过。 我得到了类似于这个工作的东西如果组件类型是一个简单的类型,比如input。用户定义的组件会产生 refs,但它们不是支持像 focus() 这样的调用的 DOM 元素。相反,它们是 React 元素。 【参考方案1】:

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

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

然后使用它来获取底层 DOM 节点:

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

如果 DOM 输入元素被包裹在另一个元素中:

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

根据 React 文档,使用带有字符串的 refs 有一些问题。详情请查看docs。

【讨论】:

如果 redux 表单定义在功能组件而不是类中怎么办?【参考方案2】:

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

我将MaterialTextField转换为类组件(在React docs中规定)。

您不能在 function 组件上使用 ref 属性,因为它们没有实例

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 特定 建议使用来自this SO question 的setTimeout() 允许宽限期。考虑@Lukas 的评论:

"这段代码可能会抛出。更好的办法是将setTimeout()返回的ID保存到组件中,然后继续 componentWillUnmount()检查超时是否仍然存在并清除 如果是的话”

将获得焦点的字段(在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
/>

注意 我正在使用 Material UI 0.x,不知道是不是这个原因 React.CreateRef() 对我不起作用(推荐的方法 since React 16.3)。

【讨论】:

我已经尝试过您的解决方案它可以工作,但是我无法将下一个文本框卡在单个输入框上。请帮帮我。 const node = findDOMNode(refs); if (node) node.focus()

以上是关于如何使用 React refs 来聚焦 Redux Form 字段?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 React 和 Redux 从另一个组件访问 ref?

如何使用 React ref 聚焦和选择复选框?

如何通过 react-redux 使用 refs 进行反应,withRouter?

单击 <div> 时,聚焦输入字段 - 如何使用 React / Redux 执行此操作?

react中input自动聚焦问题

将输入字段聚焦在React组件中 - 尝试创建ref时出现类型错误