Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can I safely use Input.prototype.inputRef? #1980

Closed
mctep opened this issue Aug 17, 2017 · 6 comments
Closed

Can I safely use Input.prototype.inputRef? #1980

mctep opened this issue Aug 17, 2017 · 6 comments
Labels

Comments

@mctep
Copy link

mctep commented Aug 17, 2017

Hello!

I need to get a DOM node from Input component. Not for focus only. For example I need to call input.setSelectionRange.

So. I have not found how to get DOM node in the documentation. But I have found inputRef in the code. May be it will be worth to add this property as "public" API in the documentation and TS definitions (like in this #1970)?

At the moment I can get input element only with findDOMNode that is not a good React practice.

@levithomason
Copy link
Member

levithomason commented Aug 17, 2017

EDIT Fixed code snippet 😊

Only public APIs are tested and versioned. There is no telling what we may do with the private methods and members between releases :) I'd strongly encourage avoiding accessing them.

The parts of the DOM for which React doesn't provide a virtual DOM abstraction (focus, setSelectionRange, etc) it requried to reach out to the native DOM, unfortunately. I'd suggest doing something simple, such as:

<Input id="my-input" />

const input = document.querySelector('#my-input')
input.setSelectionRange()

The <Input /> component will pass the id to the HTML <input />. This is a very simple and reliable DOM node access technique.


Someday JS will have truly private fields, but not quite yet.

@mctep
Copy link
Author

mctep commented Aug 18, 2017

What to do if I want to make util input component or mix some behaviour? Does make id prop required? Generate unique id? I think findDomNode(instance).querySelector('input') will be better because it does not require global ids and may be more testable.

React provides ref as standard mechanism to get DOM nodes. May be make inputRef prop for Input component?

interface InputProps {
  inputRef: (input: HTMLInputElement | null) => void
}

It looks "natural" and obviously for me as React developer. Because I used to use ref for accessing DOM nodes.

Also it will be work for Form.Field, Form.Input and others like id prop that passes to input element.

<Form.Field
  inputRef={(input: HTMLInputElement | null) => this.input = input}
/>

vs

<Form.Field
  control={
    props =>
      <Input ref={(input: any) => {
        this.input = input ? findDomNode(input).querySelector('input') : null;
      }
    } />
  }
/>

vs

componentDidMount() {
  this.input = findDomNode(this).querySelector('.some-hard-code-class-or-id input');
}

render() {
  return <Form.Field className="some-hard-code-class-or-id" />
}

In Input it needs to simply add the prop calling:

handleInputRef = c => {
  this.inputRef = c;
  if (typeof this.props.inputRef === 'function') {
    this.props.inputRef(c);
  }
}

(and other stuff for omitting inputRef prop)

This way is present in many other React libs (like React Bootstrap).
Furthermore it is recommended way in the React documentation.

@mctep
Copy link
Author

mctep commented Aug 18, 2017

I could make a PR if I have a chance to persuade you 😄

@layershifter
Copy link
Member

#1879 will introduce innerRef for all components

@mctep
Copy link
Author

mctep commented Aug 18, 2017

Hm.
@layershifter As I understand innerRef helps me to get ref on Input ReactInstance from SFC like as Form.Filed but not on input HTMLInputElement from Input. Or will it be like that:

<Form.Field
  control={props =>
    <Input {...props} innerRef={(input: HTMLInputElement) => this.input = input} />
  }
/>

?

UPD: Hm.. As I understand it will be:

<Form.Field innerRef={(input: HTMLInputElement) => void} />

<Input
  innerRef={(input: HTMLInputElement) => void}
  ref={(input: React.ReactInstance) => void}
/>

// if I want to get InputInstance from Form.Field I should use control prop:
<Form.Field
  control={props => <Input {...props} ref=(inst: React.ReactInstance) => void }
/>

@layershifter
Copy link
Member

<Form.Field innerRef={(div: HTMLDividerElement) => void} />
<Form.Input innerRef={(div: HTMLDividerElement) => void} />

Because, Form.Field renders div as root element.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants