187

I am just writing to text input and in onChange event I call setState, so React re-renders my UI. The problem is that the text input always loses focus, so I need to focus it again for each letter :D.

var EditorContainer = React.createClass({

    componentDidMount: function () {
        $(this.getDOMNode()).slimScroll({height: this.props.height, distance: '4px', size: '8px'});
    },

    componentDidUpdate: function () {
        console.log("zde");
        $(this.getDOMNode()).slimScroll({destroy: true}).slimScroll({height: 'auto', distance: '4px', size: '8px'});
    },

    changeSelectedComponentName: function (e) {
        //this.props.editor.selectedComponent.name = $(e.target).val();
        this.props.editor.forceUpdate();
    },

    render: function () {

        var style = {
            height: this.props.height + 'px'
        };
        return (
            <div className="container" style={style}>
                <div className="row">
                    <div className="col-xs-6">
                    {this.props.selected ? <h3>{this.props.selected.name}</h3> : ''}
                    {this.props.selected ? <input type="text" value={this.props.selected.name} onChange={this.changeSelectedComponentName} /> : ''}
                    </div>
                    <div className="col-xs-6">
                        <ComponentTree editor={this.props.editor} components={this.props.components}/>
                    </div>
                </div>
            </div>
        );
    }

});
Pelicer
  • 1,348
  • 4
  • 23
  • 54
Krab
  • 6,526
  • 6
  • 41
  • 78
  • The only reason that'd happen is if a) something else steals focus, or b) the input is flickering. Could you provided a jsfiddle/jsbin showing the problem? Here's a [base react jsbin](http://jsbin.com/fexoyoqi/1/edit). – Brigand Mar 22 '14 at 05:11
  • 1
    lol... well that sounds a bit annoying :P With jquery I would set an identifier for the new rendered inputfiled and then call focus on it. Not sure how the code would look in plain js. But I'm sure you can do it :) – Medda86 Mar 22 '14 at 05:13
  • 1
    @FakeRainBrigand: what do you mean by flickering? – Krab Mar 22 '14 at 05:21
  • @Krab, like if this.props.selected was becoming false, and then becoming true again. That'd cause the input to unmount, and then mount again. – Brigand Mar 22 '14 at 05:24
  • @Krab, try removing the slimScroll lines; that could be doing something weird that's causing problems. – Brigand Mar 22 '14 at 05:25
  • @FakeRainBrigand: you are right, ty. That slimScroll in componentDidUpdate causes this problem. But i thought react is just comparing outputs from subsequent render calls. That slimScroll doesn't modify output from render function. – Krab Mar 22 '14 at 05:30
  • @Krab, no but it probably messes with the DOM; so when React goes to make changes; there's something different there than what it expects. This causes problems. – Brigand Mar 22 '14 at 09:35
  • I have answered this question on one other post. Sharing the link below [https://stackoverflow.com/a/70750600/5996276](https://stackoverflow.com/a/70750600/5996276) – Wahab Shah Jan 18 '22 at 05:43

26 Answers26

139

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.

Mark Bolusmjak
  • 23,606
  • 10
  • 74
  • 129
  • 3
    This solved my problem with rendering a sub-component containing an input form. But in my case I needed the opposite -- the form was not re-rendering when I wanted it to. Adding the key attribute worked. – Sam Texas May 17 '15 at 22:13
  • 9
    adding key to the input did not help – Mïchael Makaröv Jun 09 '15 at 00:33
  • 15
    Maybe component(s) that contain your input also re-rendered. Check keys on enclosing components. – Petr Gladkikh Sep 25 '15 at 06:44
  • 2
    Thanks for the answer! Such a problem is often due to keys. I had the same problem. Moreover, I accidentally accidentally put it in general key={Math.random()} – VanilJS May 29 '22 at 20:03
107

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

Deepak
  • 2,487
  • 3
  • 21
  • 27
  • 1
    I was using a HOC inside the render function, moving the HOC call to the component definition did the trick. Somehow similar to this answer. – Mark E Jan 21 '19 at 16:59
  • 3
    I think this is my problem, but I am having trouble moving the Components outside of `render()` and the `class ... extends Component` because of the reference to `this`. e.g. `onChange={this.handleInputChange}` – Nateous Mar 14 '19 at 14:49
  • @Nateous Can you pass the function to the component as a prop? Or do I misunderstand your issue? – Abe Jul 11 '19 at 22:53
  • @Abe I probably could, but been out of this for a bit. Still using react, but I paid for a course and am getting a bit further along now. – Nateous Jul 23 '19 at 19:42
  • 34
    The morale of the story, for React class components, don't define components inside the `render` function, for React functional components, don't define components in the function body. – Wong Jia Hau Sep 23 '19 at 06:47
  • 2
    @Wong Jia Hau: What happens when you define components in the function body for React functional components? I also had a similar issue and it got fixed by applying your suggestion. – j10 Apr 23 '20 at 08:51
  • 1
    @Nateous I had exactly the same situation. HOC calls inside the `render` function that were being passed the 'this.handleChange' method and returned the components to be used. E.g. `const TextAreaDataField = TextAreaDataFieldFactory(this.handleChange)`. I simply moved the component creation to the constructor and access them in the `render` method as `this.TextAreaDataField`. Worked like a charm. – Marcus Junius Brutus Apr 29 '20 at 13:22
  • 1
    Similar issue with my component and it was all due to the "'styled-components'" being inside the render function so it would render a new styledComponent. Thanks for giving me the hint! – Kyzer May 24 '20 at 03:45
  • for functional components just move the styled.input out of functional component's definition – imran haider Oct 01 '22 at 16:14
53

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 />

ilkerkaran
  • 4,214
  • 3
  • 27
  • 42
  • 1
    `const child` should be `const Child`, in the 'Wrong' example. – David Torres Jan 15 '21 at 11:23
  • 4
    Note that you could still use such a nested child via a regular function call. For instance, `return
    {Child()}
    ` would be okay, although admittedly a bit ugly. I sometimes find it helpful to pull out non-reusable parts of the JSX expression into local closures for readability, without having to make them full stand-alone components with lots of props passing. The focus behavior is a bit of a gotcha.
    – bluenote10 May 31 '21 at 07:27
  • 2
    It **mounts** the child every time the parent re-renders – ilkerkaran Jun 07 '21 at 08:02
  • 3
    Just to expand what @ilkerkaran said, because React will run your component function (the `Parent` function) on every state update, the value of `Child` inside will be different for every render. Thus, React cannot reuse your the child component in each render, and you will end up with new elements for every update. – Yihao Gao Jun 30 '21 at 04:40
48

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

spencer.sm
  • 19,173
  • 10
  • 77
  • 88
  • 3
    This was essentially my issue. Specifically, I was passing an anonymous function to the component prop, triggering focus-loss: ` } />`, when I should've done `` – Daniel Sep 10 '18 at 14:35
  • See https://stackoverflow.com/a/47660885/11667949. In my case this helped – Shivam Jha Oct 05 '21 at 14:04
22

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.

jnotelddim
  • 1,806
  • 17
  • 32
  • 2
    A module like https://www.npmjs.com/package/shortid is also a nice way to handle something like this. – skwidbreth Dec 20 '19 at 18:37
  • See https://stackoverflow.com/a/47660885/11667949. In my case this helped – Shivam Jha Oct 05 '21 at 14:04
  • Thanks. This was also my issue. I was using `key={index+Date.now()}`. Because that changes, the component didn't preserve its state. Switching to `key={index}` solved it for me. – Hayden Linder Mar 25 '22 at 20:49
14

What I did was just change the value prop to defaultValue and second change was onChange event to onBlur.

Zoe
  • 27,060
  • 21
  • 118
  • 148
Manal Liaquat
  • 229
  • 2
  • 7
10

Applying the autoFocus attribute to the input element can perform as a workaround in situations where there's only one input that needs to be focused. In that case a key attribute would be unnecessary because it's just one element and furthermore you wouldn't have to worry about breaking the input element into its own component to avoid losing focus on re-render of main component.

spakmad
  • 880
  • 6
  • 15
  • Had to try this as last-resort workaround. I'm glad it works. There's obviously a bug in my app as the app re-renders whenever I try to type in the only search input in page. But getting `autofocus` to the input field is a start. – KeshavDulal Sep 24 '20 at 05:42
  • 1
    This worked for me too, after trying many many other solutions. It still re-renders which isn't great but it is functional. TY! – Jacob Sherwood Jan 12 '22 at 23:24
  • keep in mind if you use this with multiple inputs it will introduce other issues. Ex: typing in one field which loses focus will automatically move the user to the input field with autoFocus enabled. – CWSites Aug 29 '23 at 15:30
6

I got the same behavior.

The problem in my code was that i created a nested Array of jsx elements like this:

const example = [
            [
                <input value={'Test 1'}/>,
                <div>Test 2</div>,
                <div>Test 3</div>,
            ]
        ]

...

render = () => {
    return <div>{ example }</div>
}

Every element in this nested Array re-renders each time I updated the parent element. And so the inputs lose there "ref" prop every time

I fixed the Problem with transform the inner array to a react component (a function with a render function)

const example = [
            <myComponentArray />
        ]

 ...

render = () => {
    return <div>{ example }</div>
}

EDIT:

The same issue appears when i build a nested React.Fragment

const SomeComponent = (props) => (
    <React.Fragment>
        <label ... />
        <input ... />
    </React.Fragment>
);

const ParentComponent = (props) => (
    <React.Fragment>
        <SomeComponent ... />
        <div />
    </React.Fragment>
);
5

I solved the same issue deleting the key attribute in the input and his parent elements

// Before
<input
    className='invoice_table-input invoice_table-input-sm'
    type='number'
    key={ Math.random }
    defaultValue={pageIndex + 1}
    onChange={e => {
        const page = e.target.value ? Number(e.target.value) - 1 : 0
        gotoPage(page)
    }}
/>
// After
<input
    className='invoice_table-input invoice_table-input-sm'
    type='number'
    defaultValue={pageIndex + 1}
    onChange={e => {
        const page = e.target.value ? Number(e.target.value) - 1 : 0
        gotoPage(page)
    }}
/>
Calos
  • 1,783
  • 19
  • 28
  • True, in my case, i deleted the key and it worked perfect. I was mapping multiple textInputs – Appy Mango Apr 26 '21 at 21:21
  • It should be noted that Math.random as a key is a react anti-pattern. The whole point of a key is to tell React, "This is my component, you can find it by this key. Rerender THIS component when needed" Having a new random key doesn't let React keep track of it. – van May 05 '21 at 07:01
4

The answers supplied didn't help me, here was what I did but I had a unique situation.

To clean up the code I tend to use this format until I'm ready to pull the component into another file.

render(){
   const MyInput = () => {
      return <input onChange={(e)=>this.setState({text: e.target.value}) />
   }
   return(
      <div>
         <MyInput />
      </div>
   )

But this caused it to lose focus, when I put the code directly in the div it worked.

return(
   <div>
      <input onChange={(e)=>this.setState({text: e.target.value}) />
   </div>
)

I don't know why this is, this is the only issue I've had with writing it this way and I do it in most files I have, but if anyone does a similar thing this is why it loses focus.

Kevin Danikowski
  • 4,620
  • 6
  • 41
  • 75
4

If the input field is inside another element (i.e., a container element like <div key={"bart"}...><input key={"lisa"}...> ... </input></div>-- the ellipses here indicating omitted code), there must be a unique and constant key on the container element (as well as on the input field). Elsewise, React renders up a brand new container element when child's state is updated rather than merely re-rendering the old container. Logically, only the child element should be updated, but...

I had this problem while trying to write a component that took a bunch of address information. The working code looks like this

// import react, components
import React, { Component } from 'react'

// import various functions
import uuid from "uuid";

// import styles
import "../styles/signUp.css";

export default class Address extends Component {
  constructor(props) {
    super(props);
    this.state = {
      address1: "",
      address2: "",
      address1Key: uuid.v4(),
      address2Key: uuid.v4(),
      address1HolderKey: uuid.v4(),
      address2HolderKey: uuid.v4(),
      // omitting state information for additional address fields for brevity
    };
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(event) {
    event.preventDefault();
    this.setState({ [`${event.target.id}`]: event.target.value })
  }

  render() {
    return (
      <fieldset>
        <div className="labelAndField" key={this.state.address1HolderKey} >
          <label className="labelStyle" for="address1">{"Address"}</label>
          <input className="inputStyle"
            id="address1"
            name="address1"
            type="text"
            label="address1"
            placeholder=""
            value={this.state.address1}
            onChange={this.handleChange}
            key={this.state.address1Key} ></input >
        </div> 
        <div className="labelAndField" key={this.state.address2HolderKey} >
          <label className="labelStyle" for="address2">{"Address (Cont.)"}</label>
          <input className="inputStyle"
            id="address2"
            name="address2"
            type="text"
            label="address2"
            placeholder=""
            key={this.state.address2Key} ></input >
        </div>
        {/* omitting rest of address fields for brevity */}
      </fieldset>
    )
  }
}

Sharp-eyed readers will note that <fieldset> is a containing element, yet it doesn't require a key. The same holds for <> and <React.Fragment> or even <div> Why? Maybe only the immediate container needs a key. I dunno. As math textbooks say, the explanation is left to the reader as an exercise.

Charles Goodwin
  • 584
  • 5
  • 8
4

I had this issue and the problem turned out to be that I was using a functional component and linking up with a parent component's state. If I switched to using a class component, the problem went away. Hopefully there is a way around this when using functional components as it's a lot more convenient for simple item renderers et al.

Kyle Crossman
  • 645
  • 6
  • 12
3

included the next code in tag input:

ref={(input) => {
     if (input) {
         input.focus();
     }
 }}

Before:

<input
      defaultValue={email}
      className="form-control"
      type="email"
      id="email"
      name="email"
      placeholder={"mail@mail.com"}
      maxLength="15"
      onChange={(e) => validEmail(e.target.value)}
/>

After:

<input
     ref={(input) => {
          if (input) {
             input.focus();
          }
      }}
      defaultValue={email}
      className="form-control"
      type="email"
      id="email"
      name="email"
      placeholder={"mail@mail.com"}
      maxLength="15"
      onChange={(e) => validEmail(e.target.value)}
/>
Thiago Pires
  • 148
  • 1
  • 4
2

I just ran into this issue and came here for help. Check your CSS! The input field cannot have user-select: none; or it won't work on an iPad.

David Sinclair
  • 4,187
  • 3
  • 17
  • 12
2

The core reason is: When React re-render, your previous DOM ref will be invalid. It mean react has change the DOM tree, and you this.refs.input.focus won't work, because the input here doesn't exist anymore.

hlissnake
  • 229
  • 2
  • 3
2

For me, this was being caused by the search input box being rendered in the same component (called UserList) as the list of search results. So whenever the search results changed, the whole UserList component rerendered, including the input box.

My solution was to create a whole new component called UserListSearch which is separate from UserList. I did not need to set keys on the input fields in UserListSearch for this to work. The render function of my UsersContainer now looks like this:

class UserContainer extends React.Component {
  render() {
    return (
      <div>
        <Route
          exact
          path={this.props.match.url}
          render={() => (
            <div>
              <UserListSearch
                handleSearchChange={this.handleSearchChange}
                searchTerm={this.state.searchTerm}
              />
              <UserList
                isLoading={this.state.isLoading}
                users={this.props.users}
                user={this.state.user}
                handleNewUserClick={this.handleNewUserClick}
              />
            </div>
          )}
        />
      </div>  
    )
  }
}

Hopefully this helps someone too.

Dom Eden
  • 111
  • 1
  • 2
2

I switched value prop to defaultValue. That works for me.

...
// before
<input value={myVar} />

// after
<input defaultValue={myVar} />
2

My problem was that I named my key dynamically with a value of the item, in my case "name" so the key was key={${item.name}-${index}}. So when I wanted to change the input with item.name as the value, they key would also change and therefore react would not recognize that element

Amogu
  • 201
  • 1
  • 3
  • 7
2

For me I had a text area inside a portal. This text area was loosing focus. My buggy portal implementation was like this:

export const Modal = ({children, onClose}: modelProps) => {
  const modalDOM = document.getElementById("modal");
  const divRef = useRef(document.createElement('div')); 

  useEffect(()=>{
    const ref = divRef.current;
    modalDOM?.appendChild(ref);
    return ()=>{
      modalDOM?.removeChild(ref);
    }
  });

  const close = (e: React.MouseEvent) => {
    e.stopPropagation();
    onClose();
  };

  const handleClick = (e: React.MouseEvent) => {
    e.stopPropagation()
  }

  return (
    createPortal(
    <div className="modal" onClick={close}>
      <div className="modal__close-modal" onClick={close}>x</div>
      {children}
    </div>, 
    divRef.current)
  )
}

const Parent = ({content: string}: ParentProps) => {
  const [content, setContent] = useState<string>(content);
  
  const onChangeFile = (e: React.MouseEvent) => {
    setContent(e.currentTarget.value);
  }

  return (
    <Modal>
      <textarea
        value={content}
        onChange={onChangeFile}>
      </textarea>
    </Modal>
    )
  }

Turned out following implementation worked correctly, here I am directly attaching modal component to the DOM element.

export const Modal = ({children, onClose}: modelProps) => {
  const modalDOM = document.getElementById("modal");

  const close = (e: React.MouseEvent) => {
    e.stopPropagation();
    onClose();
  };

  return (
    createPortal(
      <div className="modal" onClick={close}>
        <div className="modal__close-modal" onClick={close}>x</div>
          {children}
        </div>, 
        modalDOM || document.body)
    )
  }
Sumit Kushwaha
  • 378
  • 4
  • 9
  • I see that you removed your `useEffect`. My issue was similar, found out that my `useEffect` was missing its dependencies. By adding it `useEffect(() => , [])`, it solved the issue – Stephane Jun 14 '23 at 20:40
1

I had the same problem with an html table in which I have input text lines in a column. inside a loop I read a json object and I create rows in particular I have a column with inputtext.

http://reactkungfu.com/2015/09/react-js-loses-input-focus-on-typing/

I managed to solve it in the following way

import { InputTextComponent } from './InputTextComponent';
//import my  inputTextComponent 
...

var trElementList = (function (list, tableComponent) {

    var trList = [],
        trElement = undefined,
        trElementCreator = trElementCreator,
        employeeElement = undefined;



    // iterating through employee list and
    // creating row for each employee
    for (var x = 0; x < list.length; x++) {

        employeeElement = list[x];

        var trNomeImpatto = React.createElement('tr', null, <td rowSpan="4"><strong>{employeeElement['NomeTipologiaImpatto'].toUpperCase()}</strong></td>);
        trList.push(trNomeImpatto);

        trList.push(trElementCreator(employeeElement, 0, x));
        trList.push(trElementCreator(employeeElement, 1, x));
        trList.push(trElementCreator(employeeElement, 2, x));

    } // end of for  

    return trList; // returns row list

    function trElementCreator(obj, field, index) {
        var tdList = [],
            tdElement = undefined;

        //my input text
        var inputTextarea = <InputTextComponent
            idImpatto={obj['TipologiaImpattoId']}//index
            value={obj[columns[field].nota]}//initial value of the input I read from my json data source
            noteType={columns[field].nota}
            impattiComposite={tableComponent.state.impattiComposite}
            //updateImpactCompositeNote={tableComponent.updateImpactCompositeNote}
        />

        tdElement = React.createElement('td', { style: null }, inputTextarea);
        tdList.push(tdElement);


        var trComponent = createClass({

            render: function () {
                return React.createElement('tr', null, tdList);
            }
        });
        return React.createElement(trComponent);
    } // end of trElementCreator

});
...    
    //my tableComponent
    var tableComponent = createClass({
        // initial component states will be here
        // initialize values
        getInitialState: function () {
            return {
                impattiComposite: [],
                serviceId: window.sessionStorage.getItem('serviceId'),
                serviceName: window.sessionStorage.getItem('serviceName'),
                form_data: [],
                successCreation: null,
            };
        },

        //read a json data soure of the web api url
        componentDidMount: function () {
            this.serverRequest =
                $.ajax({
                    url: Url,
                    type: 'GET',
                    contentType: 'application/json',
                    data: JSON.stringify({ id: this.state.serviceId }),
                    cache: false,
                    success: function (response) {
                        this.setState({ impattiComposite: response.data });
                    }.bind(this),

                    error: function (xhr, resp, text) {
                        // show error to console
                        console.error('Error', xhr, resp, text)
                        alert(xhr, resp, text);
                    }
                });
        },

        render: function () {
    ...
    React.createElement('table', {style:null}, React.createElement('tbody', null,trElementList(this.state.impattiComposite, this),))
    ...
    }



            //my input text
            var inputTextarea = <InputTextComponent
                        idImpatto={obj['TipologiaImpattoId']}//index
                        value={obj[columns[field].nota]}//initial value of the input I read //from my json data source
                        noteType={columns[field].nota}
                        impattiComposite={tableComponent.state.impattiComposite}//impattiComposite  = my json data source

                    />//end my input text

                    tdElement = React.createElement('td', { style: null }, inputTextarea);
                    tdList.push(tdElement);//add a component

        //./InputTextComponent.js
        import React from 'react';

        export class InputTextComponent extends React.Component {
          constructor(props) {
            super(props);
            this.state = {
              idImpatto: props.idImpatto,
              value: props.value,
              noteType: props.noteType,
              _impattiComposite: props.impattiComposite,
            };
            this.updateNote = this.updateNote.bind(this);
          }

        //Update a inpute text with new value insert of the user

          updateNote(event) {
            this.setState({ value: event.target.value });//update a state of the local componet inputText
            var impattiComposite = this.state._impattiComposite;
            var index = this.state.idImpatto - 1;
            var impatto = impattiComposite[index];
            impatto[this.state.noteType] = event.target.value;
            this.setState({ _impattiComposite: impattiComposite });//update of the state of the father component (tableComponet)

          }

          render() {
            return (
              <input
                className="Form-input"
                type='text'
                value={this.state.value}
                onChange={this.updateNote}>
              </input>
            );
          }
        }
Yan Takushevich
  • 1,843
  • 2
  • 18
  • 23
1

Simple solution in my case:

<input ref={ref => ref && ref.focus()}
    onFocus={(e)=>e.currentTarget.setSelectionRange(e.currentTarget.value.length, e.currentTarget.value.length)}
    />

ref triggers focus, and that triggers onFocus to calculate the end and set the cursor accordingly.

Harley Lang
  • 2,063
  • 2
  • 10
  • 26
1

The issue in my case was that the key prop values I was setting on the InputContainer component and the input fields themselves were generated using Math.random(). The non-constant nature of the values made it hard for track to be kept of the input field being edited.

1

I had a similar issue, this is fixed it.

const component = () => {
 return <input onChange={({target})=>{
    setValue(target.vlaue)
   }       
 } />
}

const ThisComponentKeptRefreshingContainer = () => {
   return(
     <component />
   )
}

const ThisContainerDidNot= () => {
   return(
     <> {component()} </>
   )
}

As the code illustrate calling the component child like an element gave that re-rendering effect, however, calling it like a function did not. hope it helps someone

Proau
  • 53
  • 3
0

Turns out I was binding this to the component which was causing it to rerender.

I figured I'd post it here in case anyone else had this issue.

I had to change

<Field
    label="Post Content"
    name="text"
    component={this.renderField.bind(this)}
/>

To

<Field
    label="Post Content"
    name="text"
    component={this.renderField}
/>

Simple fix since in my case, I didn't actually need this in renderField, but hopefully me posting this will help someone else.

Matt
  • 2,232
  • 8
  • 35
  • 64
0

With react-native

For me the issue was using styled-components/native.
After switching to the usual StyleSheet for the input component and its parents everything worked fine.

Alexandre Daubricourt
  • 3,323
  • 1
  • 34
  • 33
-1

Changing text in the input of some control can cause parent control rerendering in some cases (according to binding to props). In this case focus will be lost. Editing should not has effect to parent container in DOM.

SalientBrain
  • 2,431
  • 16
  • 18