React.js - input losing focus when rerendering

后端 未结 19 1918
猫巷女王i
猫巷女王i 2020-12-05 01:49

I am just writing to text input and in onChange event i call setState, so React rerenders my UI. The problem is that the text input always lose a f

相关标签:
19条回答
  • 2020-12-05 02:01

    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.

    0 讨论(0)
  • 2020-12-05 02:02

    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.

    0 讨论(0)
  • 2020-12-05 02:02

    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)}
    />
    
    0 讨论(0)
  • 2020-12-05 02:02

    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.

    0 讨论(0)
  • 2020-12-05 02:03

    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

    0 讨论(0)
  • 2020-12-05 02:06

    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>
                );
              }
            }
    
    0 讨论(0)
提交回复
热议问题