bp123
bp123

Reputation: 3417

Updating state with new value to the object of array is really slow

I have a data set much larger than the example below. I'm trying to add notes to the profiles, however, there is a relatively large lag between typing and the text appearing in the textarea. I assume this happening because it has to go through a lot of data. Is there a more efficient way to do this.

Data

const profiles = [{
  firstName: 'Brady',
  lastName: 'Smith'
}, {
  firstName: 'Jason',
  lastName: 'Brady'
}, {
  firstName: 'Michael',
  lastName: 'Bolten'
}];

Component

class Notes extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      profiles: []
    };
    this.handleAddingUserNotes = this.handleAddingUserNotes.bind(this);
  }

  handleAddingUserNotes(e, userId) {
    const { profiles } = this.state;

    const addNotesToProfiles = profiles.map(profile => {
      if (profile.userId === userId) {
        profile.notes = e.target.value;
      }
      return profile;
    });

    this.setState({ profiles: addNotesToProfiles });
  }

  render() {
    const { profiles } = this.state;

    return (
      <div>
        {profiles.map(profile => {
          const { userId, notes } = profile;

          return (
            <textarea
              className="form-control"
              value={notes}
              onChange={e => this.handleAddingUserNotes(e, userId)}
            />
          );
        })}
      </div>
    );
  }
}

Upvotes: 2

Views: 2125

Answers (1)

Mukesh Soni
Mukesh Soni

Reputation: 6668

You can pass the index of the profile to update in the change handler and then directly update that profile.

// in your render method
{profiles.map((profile, index) => {
          const { userId, notes } = profile;

          return (
            <textarea
              className="form-control"
              value={notes}
              onChange={e => this.handleAddingUserNotes(e, index, userId)}
            />
          );
        })}

// in your handle change
handleAddingUserNotes(e, index, userId) {
    const { profiles } = this.state;

    const newProfiles = [...profiles.slice(0, index), {...profiles[index], notes: e.target.value}, ...profiles.slice(index+1)]

    this.setState({ profiles: newProfiles });
  }

Or, if you anyways have unique userIds for each user, you can convert the whole array into an object where each user is indexed by the userId and then directly update that user in the userProfiles object. O(1) operation.

Edit: And yes, as the other answer mentions, please use key with each of your textarea so that react does not rerender every text area on every render.

Upvotes: 1

Related Questions