React.js - input losing focus when rerendering

Without seeing the rest of your code, this is a guess. When you create a EditorContainer, specify a unique key for the component:

<EditorContainer key="editor1"/>

When a re-rendering occurs, if the same key is seen, this will tell React don't clobber and regenerate the view, instead reuse. Then the focused item should retain focus.


I keep coming back here again and again and always find the solution to my elsewhere at the end. So, I'll document it here because I know I will forget this again!

The reason input was losing focus in my case was due to the fact that I was re-rendering the input on state change.

Buggy Code:

import React from 'react';
import styled from 'styled-components';

class SuperAwesomeComp extends React.Component {
  state = {
    email: ''
  };
  updateEmail = e => {
    e.preventDefault();
    this.setState({ email: e.target.value });
  };
  render() {
    const Container = styled.div``;
    const Input = styled.input``;
    return (
      <Container>
        <Input
          type="text"
          placeholder="Gimme your email!"
          onChange={this.updateEmail}
          value={this.state.email}
        />
      </Container>
    )
  }
}

So, the problem is that I always start coding everything at one place to quickly test and later break it all into separate modules. But, here this strategy backfires because updating the state on input change triggers render function and the focus is lost.

Fix is simple, do the modularization from the beginning, in other words, "Move the Input component out of render function"

Fixed Code

import React from 'react';
import styled from 'styled-components';

const Container = styled.div``;
const Input = styled.input``;

class SuperAwesomeComp extends React.Component {
  state = {
    email: ''
  };
  updateEmail = e => {
    e.preventDefault();
    this.setState({ email: e.target.value });
  };
  render() {
    return (
      <Container>
        <Input
          type="text"
          placeholder="Gimme your email!"
          onChange={this.updateEmail}
          value={this.state.email}
        />
      </Container>
    )
  }
}

Ref. to the solution: https://github.com/styled-components/styled-components/issues/540#issuecomment-283664947


If it's a problem within a react router <Route/> use the render prop instead of component.

<Route path="/user" render={() => <UserPage/>} />


The loss of focus happens because the component prop uses React.createElement each time instead of just re-rendering the changes.

Details here: https://reacttraining.com/react-router/web/api/Route/component


I had the same symptoms with hooks. Yet my problem was defining a component inside the parent.

Wrong:

const Parent =() => {
    const Child = () => <p>Child!</p>
    return <Child />
}

Right:

const Child = () => <p>Child!</p>
const Parent = () => <Child />


My answer is similar to what @z5h said.

In my case, I used Math.random() to generate a unique key for the component.

I thought the key is only used for triggering a rerender for that particular component rather than re-rendering all the components in that array (I return an array of components in my code). I didn't know it is used for restoring the state after rerendering.

Removing that did the job for me.