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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With