Ad

HTMLElement.blur Method Not Working In ComponentWillReceiveProps

- 1 answer

It seems as though using the HTMLElement.blur does not work as expected when called from componentWillReceiveProps, although HTMLElement.focus actually does work.

Simple repro case (es2015 using babel):

class App extends React.Component {

  constructor(props) {
    super(props);

    this.state = {
      index: 0
    };
  }

  componentWillMount() {
    document.addEventListener("keydown", e => this.handleKeyDown(e));
  }

  handleKeyDown(e) {
    let index = this.state.index;
    switch (e.which) {
      case 40: // up arrow
        index = Math.max(0, index - 1);
        break;
      case 38: // down arrow
        index++;
        break;
    }

    this.setState({index});
  }

  render() {
    return (
      <div>
        <SearchBox index={this.state.index} />              
        <p>Index: {this.state.index}</p>
      </div>
    );
  }
}

class SearchBox extends React.Component {

  componentWillReceiveProps(nextProps) {
    if (nextProps.index === 0) {
      console.log('focusing');
      this.textbox.focus(); // this works
    } else {
      console.log('blurring');
      this.textbox.blur(); // this doesn't
    }
  }

  render() {  
    return (
      <input type="text" ref={n => this.textbox = n} />
    );
  }
};

I have created a JSBin here that displays the unexpected behavior.

Does anybody have an explanation for this? Is there something about the react lifecycle that I have misunderstood?

Ad

Answer

It seems as though that was indeed the wrong life-cycle hook to use.

Found this nugget when I re-read the docs:

Updating: componentDidUpdate

void componentDidUpdate(object prevProps, object prevState)

Invoked immediately after the component's updates are flushed to the DOM. This method is not called for the initial render.

Use this as an opportunity to operate on the DOM when the component has been updated.

From here

I moved the relevant code to componentDidUpdate and now all works as expected.

Ad
source: stackoverflow.com
Ad