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

可紊 提交于 2019-11-28 07:36:48

问题


I am trying to use React refs to focus a Redux-Form Field when it mounts.

When I try this.refs.title.getRenderedComponent().focus() in componentDidMount, an error is thrown saying:

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

When I console.log this.refs, it is mostly an empty object and sometimes identifies 'title' as being a ref, but it is not dependable.

Am I using refs incorrectly? My code is below for reference.

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

...

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

回答1:


Please try setting ref using callback function:

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

and then use this to get underlying DOM node:

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

of if DOM input element is wrapped in another element:

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

According to React docs using refs with a string have some issues. Please check docs for more details.




回答2:


I use redux-form and Material UI and had to do the following. MaterialCheckboxField and MaterialTextField are custom components in my project wrapping material-ui/{Checkbox,TextField}.

I converted MaterialTextField to a class component (as stipulated in the React docs).

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

import { findDOMNode } from "react-dom";

The field setting focus (within the render() method):

<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 this SO question. 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"

The field that will receive focus (within the render() method):

<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).



来源:https://stackoverflow.com/questions/42459190/how-to-use-react-refs-to-focus-a-redux-form-field

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!