D
D
Dmitry Potylitsyn2017-08-16 01:22:13
JavaScript
Dmitry Potylitsyn, 2017-08-16 01:22:13

How to make mobx NOT re-render all children of an array?

Let's say we have an array of elements (child components), we need to render it on load. And then add/remove its elements. The challenge is to make it as efficient as possible in terms of component rendering speed.
Actually, I began to seriously think about these issues, just after using the mobx developer's tools, which clearly show the render time of components.
When an array changes, MobX redraws absolutely all child elements, encountering an ordinary view construct, despite the fact that its elements in the store are "decorated" in @observable. It does not accept key attributes, because ignores shouldComponentUpdateelements.map(data => <El data={data} />);(Based on the documentation, I tried to find some workarounds, crutches, but even with the latter, it’s extremely sparse).
Conducted performance tests for my initial data:
The child element is a material-ui checkbox, a calculated text label and two control icons. Nothing special in general.
MobX is 150 children, the next one (151) takes about ~145-155ms to create . Approximately the same result was produced by "bare" React, generating different keys each time, which unequivocally re-renders the entire list again.
But having written the banal shouldComponentUpdate (return false for all former child elements) to the usual React'y, the processing of these actions took only 10-15ms.
I would like to somehow solve this problem ... or, perhaps, find a worthy justification for such behavior.
[Update#1] : For more clarity, I posted a project illustrating the problem (without experimenting with computed):
Project: https://github.com/Naararouter/mobx-problem-001
Developer tools: https://chrome.google .com/webstore/detail/mobx-dev...
I would be infinitely grateful if you can look and find a solution, or direct me along the "true path".
Ps: the project is a model of a real task, as a result, something similar to a banal ToDo List turned out. I tried to abstract as much as possible from the context, preserving the structure of the components in real conditions.

Answer the question

In order to leave comments, you need to log in

2 answer(s)
A
Andrey Antropov, 2017-08-16
@Laiff

Perhaps it makes sense to look at https://mobx.js.org/refguide/computed-decorator.html plus if there are no keys, then the react starts to feel sad, so the keys must be set at least by index

B
bgnx, 2018-01-19
@bgnx

The problem is in your code, in each child component you are accessing an entire array, mobx sees that the array has changed, so you need to call a re-render of all components that access the array. In your case, the call occurs because in the ProblemChildren component you call the getCurrentFromStore() function in the render method, which calls the .getCurrentFromKey(this.props.id) function, which already refers to the this.problemEntitiesList.find(x => x) array itself .id === key) which means that any change in the array (adding, deleting, overwriting an element) will re-render this component. If you do not access the array, then there will be no re-render, as in this example https://codesandbox.io/s/wynyl96j07 You need to rewrite it so that the necessary data is passed through the props because there is some kind of trash in your code - why render by passing the ID so that later in the component itself you can pull out the same data object through the this.props.ProblemStore.getCurrentFromKey(this.props.id) store? Don't you think that it would be easier to immediately pass the data object through the prop and not do double work? At the same time, there would be no extra re-renders. <ProblemChildren key={data.id} id={data.id} />

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question