简体   繁体   中英

React JS Input type text loses focus after keystroke

Fiddle Demo I'm trying to update the state array which contains an array of data objects.

State in constructor:

this.state = {
        data: [
        { name: "Abc", age: 12 },
        { name: "Xyz", age: 11 }
      ]
    }

Handlers:

handleName(idx, e){
        const data = this.state.data.map((item, sidx) => {
            if (idx !== sidx) return item;
            return { ...item, name: e.target.value };
        });

        this.setState({ data: data });
  }

  handleAge(index, e){
        const data = this.state.data.map((item, sidx) => {
            if (idx !== sidx) return item;
            return { ...item, age: e.target.value };
        });

        this.setState({ data: data });
  }

Render Method :

render() {
      console.log('render');

        const Input = () => this.state.data.map((item, index) =>{
            return (
            <div>
              <input type="text" value={item.name} onChange={(e) => this.handleName(index, e)}/>
              <input type="text" value={item.age} onChange={(e) => this.handleAge(index, e)}/>
            </div>
          );
        });

        return (
            <div>
             <Input/>
          </div>
        )
      }
    }

I know in every keystroke the render method is refreshing the dom, is something wrong with my rendering elements. Any suggestions ?

While returning element from within the map you must have a key assigned to them otherwise a new instance of it will be created always on a new render. Also you must not create a component within render

render() {
  console.log('render');

    return (
      <div>
         {this.state.data.map((item, index) =>{
        return (
        <div key={index}>
          <input type="text" value={item.name} onChange={(e) => this.handleName(index, e)}/>
          <input type="text" value={item.age} onChange={(e) => this.handleAge(index, e)}/>
        </div>
      );
    })}
      </div>
    )
  }
}

Working DEMO

Because on every re-render it is creating a new instance of the component woth values from state,

You need to take the function out of render or simply just use it like this

render() {
  console.log('render');  
    return (
      <div>
         {this.state.data.map((item, index) =>{
           return (
             <div>
              <input type="text" value={item.name} onChange={(e) => this.handleName(index, e)}/>
              <input type="text" value={item.age} onChange={(e) => this.handleAge(index, e)}/>
             </div>);})
         }
      </div>
    )
  }
}

Demo

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