I have a list of components (~50-100), these components are quite advanced; they contain a lot of child elements that obviously takes some effort to be drawn out.
The result is that the UI "freezes" 1-2 seconds when navigating to the page, it actually freezes before getting to the page.
The UI is also a bit laggy when all the components are loaded.
I'm thinking it should be possible to load them in chunks in some way? Or only draw the full component out if it's visible on the screen somehow, and have a skeleton component when it's not in the viewport.
What is the recommended approach here?
Thanks in advance.
You must avoid useless renders with memo.
Be careful not to call APIs for no reason.
Also you should use useCallback and useMemo to avoid call methods which return same value for children components.
Context API is a good option to avoid Drilling states as props to nested components.
You could use lazy loading to render children components along with scroll as well.
Related
I'm trying to implement a generic Drag-and-Drop module that I may or may not release on NPM.
I took inspiration from an already existing DnD module which consisted of essentially two main components: Draggables and DropZones.
The Draggable components would enable any content that they enclosed to be dragged around, and DropZones were the components that would react to when a Draggable component was dragged in/out of them and/or dropped onto them.
The module's functionality was too basic for what I needed, so I set off on making my own.
Everything has been going fine except for one aspect: measuring the absolute position of a large number of components in order to find their corresponding bounding shapes for collision detection.
Currently, I've been using the View's measure method to measure the absolute position and size of my components, however, if you call this method too many times within a short period of time, React Native will throw this error: Warning: Please report: Excessive number of pending callbacks: 501. Some pending callbacks that might have leaked by never being called from native code and it lists the offending method as {"module":"UIManager","method":"measure"}.
If I make a basic for loop that repeatedly calls the measure method, I can get it up to just over 500 iterations before React Native complains (this number may be hardware-dependent; I'm not sure).
Also, the same problem happens when using the View's other measuring methods (e.g. measureInWindow, measureLayout).
What's even worse is that up until now, I have been calling the measure method in a View's onLayout callback, however, I recently discovered that onLayout does not get called when a style changes that doesn't directly affect the given View (such as when a parent component's margin changes).
This means that the given components can be re-positioned (relative to the screen) without them knowing about it.
Because of this I will have to use a different means of notifying my components that they need to remeasure themselves.
I thought about using some of the life-cycle methods that pertain to component updates, but that would most likely be even worse, because most of them get called every time the component updates which is far more often than a layout happens.
Edit: One other problem with using the life-cycle methods that pertain to component updates is if a parent component prevents it's child components from being updated (such as through shouldComponentUpdate).
The bulk of my page is essentially a list of 40-100~ish components, each containing about 11 KB of data (in JSON format). The problem is that 100 times 11 KB makes 1.1 MB, which seems to be a little too memory-intensive to store in the Redux state for browsers on older mobile devices. It makes my gorgeous CSS animations look choppy and buttons take about a second to toggle on/off state.
Because each component is exactly 148px tall, my first thought was to use a virtual list (Virtuoso) which only renders as many items at a time as can fit on the screen (which is like 5-8 tops). This made the first time render much faster, but did nothing to make animations smoother, which definitely confirmed it's mostly a memory issue.
So, if I can't store and keep all my data in the state object, then I need to do something similar to Virtuoso and only keep as much data as I need to render the current screen. Now, I'm not exactly sure how Redux works internally, but if the state is immutable, doesn't that mean that everything that ever goes there stays there? And wouldn't that mean I'm trying to do something impossible, or at the very least anti-pattern?
Oh, and to make things worse, the data will need to be updated every 3 seconds, which means a component will sometimes disappear, only to reappear with the next update. I haven't tested how this would affect Virtuoso scrolling yet, but I don't exactly expect perfect plug-and-play behaviour.
I would appreciate ideas on how to solve this with redux and (possibly) its middleware, since it's the only architecture I'm familiar with atm and switching to e.g. Flux would mean having to learn it from scratch AND rewrite about 2000 lines of redux code.
I have never used Virtuoso, react-virtualized or react-window, but this looks like an issue that you can tackle with one of those libraries.
Do other parts of your React application care about the data you are rendering in the list?
If not, put the data in this component's local state and not in Redux.
If they do, maybe try to set this huge list in localStorage when the component mounts, unset it when it unmounts, and use the component's local state to select start / end indexes to pick a slice of the data.
See also: https://blog.jakoblind.no/is-using-a-mix-of-redux-state-and-react-local-component-state-ok/
I'm working on refractoring a medium size app, around 20k lines of code distributed in 20 components. The whole state of the app covers more than 200 properties and to be be faster I built the app by passing the whole state to my child components. Now I'm concerned about the speed of the page.
I wanted to have short and readable components. If I decide to pass single properties I will have some components with 50 properties or more. Does it make sense to do that in order to gain speed?
Thanks for the help
From pattern point of view it is much cleaner to use global state management like redux to share states between components than passing state to child.
In some other cases the solution is even easier and still not require passing states.
YES
React will only render the changes that have been made since the last render, if parts of your child elements haven't been modified they will not be re-rendered to the DOM.
as an example this:
<Content
accounts={this.state.accounts}
showBalance={this.state.showBalance}
withdraw={this.state.withdraw}
deposit={this.state.deposit}
current={this.state.current}
depositAmount={this.state.depositAmount}
handleDeposit={this.state.handleDeposit}
handleRm={this.state.handleRm}
amounts={this.state.amounts}
getWithdraw={this.state.getWithdraw}
/>
could be replaced with
<Content {...this.state} />
I've been testing the performance of animated React components using different methods. The two that seemed most interesting to me were:
In parent component, keep position of children in state and update using requestAnimationFrame then pass props to a bunch of children, which move using translateX() for better performance
maintain position state in each of the children and update its position itself
I saw similar performance between the two. I know that React batches multiple calls to setState, but I'm wondering if it still batches the calls among separate components. In the first approach, setState is only called once per frame. In the second approach, we call setState for each component each frame.
Which is the better practice?
Perhaps I'm not using enough child components to see a real difference, but if anyone with more knowledge of React's reconciliation process has any ideas I'd love to know.
There are around 3 hundred components rendered inside the wrapper component and its taking to much of time to render. But I need thousand of components to get rendered inside the wrapper container. How can I achieve this without any performance issues while rendering the components
Image shows the rendering time taken by 300 components which is too much
If you have a scroll and all of your components are not in the viewport at the same time, you may use the Proxy Pattern.
There is an ember addon called ember-in-viewport to detect whether your component is in viewport or not. By using it, you may implement the proxy pattern.
Here is a sample twiddle. At the application.hbs, if you use my-proxy-component instead of my-component, page rendering would be nearly 3 times faster.
These tips are kinda hacky but might help:
You might want to lazy load some of the components, like for example load the most critical ones and then load the rest changing a computed property after a fixed timeout on didRender event (during the idle state).
For example:
onDidRender: Ember.on('didRender', function() {
Ember.run.later(() => {
this.set('displayLazyItems', true);
}, 2000);
})
Another thing you might want to do is inline code instead of creating a new component for small items. Rendering those might take some serious time.
Record a timeline and ensure that the performance is actually coming from render time, sometimes is actually some javascript execution or loading that is messing up.
Lastly, ember 2.10 includes glimmer 2, this new render engine can optimize render time up to 50%, you might want to consider using it.