dieTrying
dieTrying

Reputation: 377

React set focus on input[type="number"] with conditional render

After reading React set focus and React focus with timeout I'm still a little bit confused what is the right cross-browser options for setting focus on input.

I have a problem with conditional rendering inputs which might have focus after rendering in table, where input placed in td.

1)Solution with componentDidUpdate:

//...
componentDidUpdate() {
  this.input && this.input.focus();
}

render() {
  const show = this.state.isShown;

  return (
    <td className="editable">
      {!show ? (
        <input
          type="number"
          ref={(input) => { this.input = input }}
          value={this.state.value}
          onBlur={this.save}
          onKeyPress={e =>
            e.which === 13 || e.keyCode === 13 ? this.save() : null}
      />
    ) : (
        <span onClick={this.onTdClick}>{this.props.name}</span>
      )}
    </td>
  );
}

This solution works in Chrome, IE11, Edge, but does not work in latest Firefox(input event does not appears afterspan was clicked.

2)Solution with requestAnimationFrame:

//...
componentDidUpdate() {
  if (!this.state.isShown) {
    requestAnimationFrame(() => {
      this.input && this.input.focus();
    })
  }
}

render() {
  // same above
}

This solution works in Chrome, IE11, Edge, but still Firefox does not show input when trying to set focus.

3)Solution with setTimeout(callback, n):

  //...
  componentDidUpdate() {
    if (!this.state.isShown) {
      setTimeout(() => {
        this.input && this.input.focus()
      }, 50);
    }
  }

  render() {
   // same above
  }

This case works for Chrome, IE11, Edge and (finally) Firefox, but seems this is the most "ugly" one.

P.S. autoFocus attr is not for this case, here I have conditional rendering, so need set focus after click.

So, my questions is: have we got a right way to solve this w/o setting setTimeout for Firefox?

Live testing example: codepen

Upvotes: 5

Views: 2519

Answers (1)

Nazariy
Nazariy

Reputation: 417

import React from 'react';

const MyInput = React.createClass({

    componentDidMount(){
        this.elem.focus();
    },

    render(){
        return(
            <input
                ref={(elem) => {this.elem = elem}}
                type="text"
            />
        );
    }
});
export default MyInput;

Render <MyInput/> where you want. After render it will be with focus. Tested on Safari, Chrome, Firefox.

Upvotes: 2

Related Questions