2

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>
    );
  }
}
bp123
  • 3,217
  • 8
  • 35
  • 74
  • You can try https://immutable-js.github.io/immutable-js/docs/#/ . It is a little bit complex but it is specifically made to have good performance for huge structures – Arseniy-II Aug 14 '19 at 05:09
  • `this.state.profile` is always an empty array in the `Notes` class. Nowhere you are passing it as a prop or even as global. Can you please update your code for us to understand it better? :) – UtkarshPramodGupta Aug 14 '19 at 05:09
  • You probably just need to set a `key` prop on your `textarea` components. See https://stackoverflow.com/a/28329550/864233 and https://reactjs.org/docs/lists-and-keys.html for more information. – romellem Aug 14 '19 at 05:10
  • Based on the way I phrased the question, I think @Mukesha is correct, however, I think the 'React' way to fix this was to split the individual profiles into a new component. This solved my problem completely. – bp123 Aug 14 '19 at 05:44

1 Answers1

1

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.

Mukesh Soni
  • 6,646
  • 3
  • 30
  • 37
  • Why in both cases you're making copy of an array (which for large arrays is probably main source of slowdown?). `profiles[index].notes = e.target.value;` and `this.setState(profiles);` should be order of magnitude faster? Or am i missing something major? – Radosław Cybulski Aug 14 '19 at 05:21
  • You are not. In the first case you iterate over each element. So it's O(n). In the other case you are only breaking apart the array. That operation might need some array allocation internally, but should be super optimized. Specially for slice operations. I am assuming that browsers or javascript engines internally reuse the same memory as allocated to the original array. – Mukesh Soni Aug 14 '19 at 06:14
  • Hmm, i'm not that versed in web devel, but original `profiles` array might be kept somewhere. So by code itself it's unlikely the optimizer can figure out, that it can reuse memory. Maybe with JIT in runtime. Nevertheless thank you. – Radosław Cybulski Aug 14 '19 at 09:29