Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practice for mapping an array in React app for performance optimization

I have a simple dictionary app I'm making that returns search results. A search is queried on every onChange of the search field using a lokiJS in-memory database for the dictionary, so the results come very quick.

It is important for me to optimize the rendering of the results, so that the 50 or so filtered search results keep flowing as the user types and the queries happen on each key stroke.

Here's what I've been doing so far: (this works but is it the best/fastest way?)

Each (sync) query of the database returns an array of objects, which I then map with something like this:

queryDB(query) {
  const results = queryLokiJsDB(query);
  const resultsMapped = results.map((mpd) =>
        <dl key={mpd["$loki"]} onClick={() => this.clickFunction(mpd.p, mpd.f)}>
          <dt>{mpd.p} - {mpd.f}</dt> <dd>{mpd.e} <em>{mpd.c}</em></dd>
        </dl>);
  this.setState({ results: ( 
    <div>
      {resultsMapped}
    </div>
  )});
} 

Then, once I have the results mapped like that, I add the mapped components to the state, and then the screen gets rendered with the new results.

render() {
  return (
    <div>
      <SearchBarStuff />
      <div className="results-container">
          {this.state.results}
      </div>
    </div>
  );
}

I made this when I was just learning React and I understand that people consider it really bad practice to store components in the state.

I was wondering what the best practice in terms of performance optimization would be (and code cleanness). Should I store the results array in state then render then map them into components in the render function? Would that cause any performance hits?

Another answer said that "A function in the render method will be created each render which is a slight performance hit."

And why is it so bad to store components in state? Is it just for code clarity? Keeping the state small? I appreciate your help and patience.

like image 932
Adam D Avatar asked Nov 08 '22 03:11

Adam D


1 Answers

I'm not quite sure but I am thinking the same problem as @larz explained in comments. Also, as you mentioned the state will be clearer. So here what would I do if I were you.

First, set your state just with the results:

queryDB(query) {
    const results = queryLokiJsDB(query);
    this.setState({ results });
}

Then, map through the results but instead of creating your JSX immediately I would use a separate component. Pass it mpd (the element) and onClick function with its reference.

render() {
    return (
        <div>
            <SearchBarStuff />
            <div className="results-container">
                {this.state.results.map( mpd => (
                     <Item key={mpd["$loki"]} mpd={mpd} onClick={this.clickFunction} />
                ) )}
            </div>
        </div>
    );
}

Use the Item like that:

const Item = ( props ) => {
    const { mpd, onClick } = props;
    const handleClick = () => onClick( mpd.p, mpd.f );

    return (
         <dl onClick={handleClick}>
            <dt>{mpd.p} - {mpd.f}</dt> <dd>{mpd.e} <em>{mpd.c}</em></dd>
         </dl>
    );
}

In this way, you are not using an arrow function in your onClick handler, so this function will not be recreated in every render since we use the reference.

like image 91
devserkan Avatar answered Nov 14 '22 23:11

devserkan