简体   繁体   中英

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 after span 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.

PS 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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM