Werner
Werner

Reputation: 13

React changing value of object change order of array

I'm kinda new to React and i try to figure out how to change the state of my object's. But when i change the state in my input field the field is rerenderd at the bottom.

How can i keep my input field on the same place as it's renders the first time.

class App extends Component {
    state = {
        persons: [{
            id: 0,
            name: ''
        },{
            id: 1,
            name: ''
        }]
    }
    
    changePersonNameHandler = event => {
        const id = parseInt(event.target.id);
        const newPersonName = event.target.value;

        this.setState({
            persons: [...this.state.persons.filter(i => i.id !== id),
                {
                    id,
                        name: newPersonName,
                }
            ]
        })
    }
    
    render () {
        const {persons} = this.state;
        
        return (
          <div>
            <ul>
              {persons.map((i, index)  => (
                  <li key={i.id}>
                      <label>Name: </label>
                      <input id={i.id}
                           value={i.name}
                           onChange{this.changePersonNameHandler}/>
                  </li>
                  )
              )}
            </ul>
          </div>
        )
    }
}

Upvotes: 1

Views: 4257

Answers (2)

UjinT34
UjinT34

Reputation: 4987

filter removes an item and you lose its position. To modify an item and keep its place in the array use map. Also it is better not rely on this.state to get a new value for setState. You should use setState(oldState => newState) instead.

changePersonNameHandler = event => {
    const id = parseInt(event.target.id);
    const newPersonName = event.target.value;

    this.setState(old => {
        const persons = old.persons.map(
            person => person.id !== id ? person : {id, name: newPersonName}
        );
        return {persons};
    })
}

Upvotes: 2

samb102
samb102

Reputation: 1114

Each time you're doing a change, you put the edited person at the end of the array in your handleChange method.

Just invert the edited one and the existing ones in setState and it will do the trick.

this.setState({
  persons: [{
      id,
      name: newPersonName,
    }, 
    ...this.state.persons.filter(i => i.id !== id)
    ]
  })
}
  • There is a missing = sign after onChange in the code you gave but I guess in your local code it's ok.

Upvotes: 1

Related Questions