React: hiding vs removing components [closed] - javascript

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
This question is about architecture more than coding.
Here's the case. In React sometimes we want to hide components. For example, when user opens new page in SPA, when some toast is closed, etc. We can hide them with adding display: none. Or we can remove them from the virtual DOM.
// Hidden div
<div style={{ display: 'none' }}/>
// Removed div
{false && <div/>}
And some of our seniors othen use the first variant. Even if they hide entire page. That's what they say about this method: "This case React prerenders needed content, so when the content must appear, it takes less time".
But in this case we can't use lifecycle hooks, because even when component hides, it's not removed. But the main problem as I think, is that real DOM becomes gigantic. And that's brings slowness, isn't it?
So, what is better?
I didn't found any conversations about this question. Maybe you could help me.
EDIT 1: Despite the fact there are some answers I'd like to know more opinions. So, I decided to open up a bounty

Let's compare some of the differences between these two methods for toggling HTML element visibility, element toggling (aka display: none|block) and JSX short circuit rendering
Simplicity - As you know JSX has been optimised for reactively toggling markup, so it will not print false, true, null and undefined, hence you can write shorter logics in there. Similar case for not using template literals instead of JSX was brought by Facebook https://facebook.github.io/jsx/#why-not-template-literals. Simplicity leads to maintainability, in the long run it will help your app not become another spaghetti nonsense.
isShown && <div />
vs
<div style={{ display: isShown ? 'block' : 'none' }} />
Performance - Spanning way more nodes is never good for performance and memory usage, generally it varies per application. It can be benchmarked using Chrome's Performance Monitor or the React Profiler. But more importantly React builds new performance optimisations around the knowledge that you would follow https://reactjs.org/docs/jsx-in-depth.html rather than using other tricks. Given that some or most of your codebase is using the element toggling approach and there is a new version of React with performance improvements chances are you will probably spend weeks into refactoring to benefit from it.
Bugs - With JSX short circuit rendering you must remember not to use something like elements.length && elements.map(({ text }) => text) as given that the elements array has no members, JSX will print 0 instead of nothing. On the other side setting visibility with display: block almost certainly will lead to flex, inline, inline-block, table elements to be set to block. The second bug is harder to find as you need to deal with css styles or css-in-js.
Consistency - Given that JSX short circuit rendering is the recommended method by the maintainers of React it will be present in most React projects. But say you mix it with the old school display toggling method and any new developers joining the team will question why you are using both. Mixing these will most probably lead to bugs as well where an element might be shown by JSX and in the same time hidden with display: none or vice versa.
Debugging - using React Devtools or Elements while having lots of elements being set to display: none is a nightmare as it will be polluted with nodes that you simply don't need there
I reckon senior devs are used to toggle elements with display as it is considered old school. It might also be a legacy of converting your app from jQuery to React. It was the only way of making UIs back in the days. Some habits or shall I say mental models are quite sticky. Now days in a React project I will consider the above a hack.
I would advice against using any other way of toggling visibility of markup in React but the standard JSX short circuit rendering isShown && <div />. In my long experience of writing React apps I try to stick to the simplest and most expressive code, that all developers from uni graduates, to juniors, to seniors would expect as per best practices and wouldn't have trouble reading, so they reuse rather than write the nth version of the same component.
EDIT: As it was mentioned in other answers, transition animations are usually done with react-transition-group package that is only working with JSX short circuit rendering.

Note: to those, not interested in long-winded explanations (in attempt to score rep bounty), followed by irrelevant examples and conspiracies, here's a quick one
TL;DR
You need to bear in mind the following to make your own decision, depending on your specific use case:
Hidden DOM elements are ignored while building render tree, so the only performance gain you may possibly see when control visibility by styling, may be caused by building DOM tree ahead of time.
When visibility is controlled by style settings, excessive DOM size may slow down your browser unnecessarily.
On the other hand, from React prospective, applying conditional rendering (and rebuilding the tree of descendants, once you decide to make them visible) seems to be slightly more expensive than changing single attribute.
Considering the above, for complex components (large DOM subtree) with relatively high odds of being visited (or being shown most of the time over the course of user interactions) it would make sense to toggle visibility styling. Otherwise, conditional rendering seems to be a better option from performance standpoint.
p.s: Other than performance you may be concerned with
SEO - if you render conditionally some navigation pannel/dialog, that holds links pointing to other pages of your app, those links won't appear in your DOM, hence can't be traversed by crawler and indexed, which won't be the case if you toggle visibility with style settings;
UX - if according to design there has to be animation (e.g. fade in/out) of UI element appearing/disappearing on screen, if you use conditional rendering, you might need more advanced techniques to make sure animation still works not to frustrate your users

Some facts
Code to pixel is a multi-step process. It's generally expected, javascript to take around 10-12ms to maintain 60fps.
Premature optimization is a bad idea. So measure -> optimize -> measure -> repeat.
The short answer depends. Some possible scenarios.
Fetching(API, img, video)
Usually ends up fetching even before the user visits the page.
For eg the below img would be fetched even before the user visit the page and the same goes for any API request.
<div style={{ display: "none" }}>
<img src="https://picsum.photos/200/300" />
</div>
So if you are API heavy or image-heavy takes a note of it. There is a way to prevent this behaviour but isn't possible in order version.
Also, you could prefetch asserts based on priority if asserts are the only reason why you prerender.
Animation
It's already been posted multiple times but there is an easy and elegant solution. write a wrapper(HOC preferred) around the actual component and let it have both display none for an empty div and conditional rendering for the actual component. So if you want to animate boom you are good to go.
Performance
In code to pixel conversion, JS takes a significant time especially for the very first time of code running. Refer JS engine internals Start here
So if you execute cat page JS with a display none property while the user wants to see a dog page good luck retaining the user.
On the other hand, if you were successful doing with less or no performance hit please post your method I would love to read it.
Ideally, you could use SSR with prefetching the HTML to solve this issue as well, since it just flushes out RAW HTML user just needs to render that in the browser which is equivalent to changing display property.
On the other hand, if you just use it to render some static pages changing the display property is probably ok but it's debatable on why react in the first place.
So in a general sense personally I would prefer conditional rending unless if the odds of visiting the whole page is high as #Yevgen Gorbunkov stated.

Well if you want to use lifecycles there are workarounds for that as well.
if you are using functional components then you can manage the rerenders using the dependency props.
Its true dom size can slow you down if you use it excessively https://web.dev/dom-size/
But is better if those components are constantly being updated rather then rendering a new component on demand.
If its a list of items and its gigantic i suggest you to take a look at https://react-window.vercel.app/#/examples/list/fixed-size or https://bvaughn.github.io/react-virtualized/#/components/List

Personally, I prefer to remove, but that then prevents fade out animations. I like to use something like this to get the benefits of both.
const FadeContainer = ({ show: showProp, children }) => {
const [show, setShow] = useState(showProp);
const timeoutRef = useRef();
useEffect(() => {
if (showProp) {
setShow(true);
} else {
timeoutRef.current = setTimeout(() => setShow(false), 500);
}
return () => clearTimeout(timeoutRef.current);
}, [showProp])
return show && (
<div style={{ opacity: showProp ? 1 : 0, transition: "opacity 0.5s ease" }}>
{children}
</div>
);
}

"It depends" is an answer to a lot of questions.
This discussion has also popped up within the Frontend team I am part of at work. A few things were taken into consideration over the time.
With React routing is mostly handled on the client side, giving you a lot of flexibility on how to handle the rendering of components and pages.
Does the site you work on have an extensive landing page, maybe with very few and small other pages? Then I suspect the additional DOM elements and HTML file size initially fetched and loaded into the DOM have little impact. Making them invisible with styling is perfectly fine.
Does the site have very many pages, and is it unlikely that the visitor is going to ever visit the vast majority of these? Then it would have a number of downsides hiding all those extra DOM elements with css. Think initial load time, the assets needing to be fetched can grow noticeably. In that case implementing code-splitting for different routes is probably a good idea, making hiding elements no longer an option.
A middle ground is also very possible here. It could make sense to code-split based on the (sub)routes your site has. But using css to hide elements like modals, elements that pop up when hovering over something, etcetera. So that everything within that page is snappy.
Like mentioned in other answers, using a prop to set visibility is a good approach to make fade ins and fade outs (which is of course harder) possible. Samuels answer is a nice proposal. Otherwise React Transition Group is used in my team to set classed based on transition states, allowing to animate the element in and out as well as removing the component from the DOM if you want.
I think this is an interesting question and hope to be able to hear more opinions from others too.

I think both have advantages and disadvantages.
Please see this article.
Compare the performance between hiding React components with css and state management
Hiding components using display CSS property will be faster in toggling show and hide.
Removing components using non-CSS way, when conditional state value is false, it has one less component to rerender, so that it improves performance.
Which is better depends on your choice of your project.

Related

React - component for every styled element?

I'm learning React.
It seems React highly promotes composition. Create React App even advises against reuse of css class.
Let's say I have a container, which is a white box, with nice rounded corner and shadow, etc. It can contain anything. That's it. No logic. Not much html except a <div>
Traditionally, I would just create a global css class named .white-box and then apply it to any <div> that I want it to be this white box.
I know in React you can do this, too. You can do whatever you want. But what is the general practice? From what I found online, it seems I should create a component for it and put any children inside:
<WhiteBox>
<div>anything</div>
</WhiteBox>
Isn't it overkill? What are the benefits of doing this? Should I create a component for everything that can be re-used, even when it is such a small thing?
This is honestly a matter of personal preference and experience.
For example, the seemingly pragmatic way would be to use a .white-box class on a div; it's super easy and requires no imports!
A bit later down the line, you decide that every white box inside some other control needs a bit more shadow, so you go and add a CSS rule for .some-component .white-box, and bam, now you got a shadow'ier white box without messing with the original CSS class. Nice and easy!
The problem with that is that when you do it once or twice, it's fine. But you'll soon develop a habit for "patching" the class name rules for specific purposes, and before you know it you're mixing rules without knowing it yourself, which is exactly what it says on the tin: Cascading Style Sheets.
I've been there myself, and it's no fun to maintain. Now I create components for everything, even things as simple as a white box. The trick is to name them right; you wouldn't call it WhiteBox because if you change the color of the box down the line, the rest of your code is a lie. ;) Instead, call it something like ContentBox; something that describes it's purpose, not what it looks like. Then use props to determine what characteristics the box should have:
<ContentBox shadow padded rounded>Awesome</ContentBox>
I'm personally a big fan of CSS Modules because they make sure that class rules never clash which avoids the issue outlined above entirely. Instead, if you want a class to inherit some styles from another, CSS Modules lets you compose them together.
Example CSS modules file:
.root {
background-color: #fff;
}
And a React component:
import React from 'react'
import styles from './ContentBox.css'
export default function ContentBox({ children }) {
return (
<div className={styles.root}>{children}</div>
)
}
The actual classname being used is actually something like ContentBox__root_abcd123random so even if you have another CSS file with the same .root class, the rules never clash.
An added bonus of doing it this way is that your components are now portable to other projects because it only depends on styling within the CSS file that ships with the component. I've enjoyed great reuse using this strategy across many internal web apps at our company.
That's right. It's not overkill when you are confident that features will be the same across your app. For example, you can have the nice shadow styles as you said, or guarantee that all containers have white background or might have a fluid prop which will expand the element for the whole parent width.
In fact, there are React frameworks like Semantic UI React that do exactly like this.
Every time you see yourself designing some HTML that should be consistent in your codebase, that should ring a bell for creating a single unique component for it. And if you think your components are big enough, maybe you should break them down.
This approach makes your code easy to test, once it's way more easier to test small stuff with limited and well-defined functionalities than a big component which several features. Once you glue them together, because of React one-way data flow approach, you know exactly why stuff is not working - you now have simple components for each feature, and if they are not working as expected, there is only one flow where data might have came.
As a beginner those concepts might be hard to grasp. But once you start digging into large codebases and projects, you will see how "modularizing" your application will have long-term benefits.

Angular 4 - it is more expensive to handle styles of a generic component or work with specific components

I'm working on a hybrid application for which I need a toolbar. This toolbar must handle different forms and functionalities, in some cases contains a title, other buttons and links and in others an autocomplete, then my questions is if is more efficient to build a dynamic component that accepts all these elements or work on different toolbar's that will be inserted and removed from the DOM as needed.
Thanks!
A dynamic toolbar will be faster, because angular wont need to re-render the whole toolbar each time it changes. It's smart enough just to find the stuff it needs to update.
Also it will make your code easier to maintain I think. Having multiple toolbars, probably with some shared logic/elements will cause repeated code.
Also you will probably have less lines of code with a dynamic toolbar, perhaps slightly reducing the size of your project. I suspect that wont be significant. Honestly, I think the biggest advantage wont be speed but cleaner, more maintainable code in general.
It depends on whether you are using lazy loading or bundling your entire App in one main.bundle.js
In the first case, you want to ship the strict minimum to the browser as it's needed. Therefore, you want separate component for each use case.
In the second case, it makes your app lighter to create on single component to handle different toolbar use cases.
To demonstrate this, (assuming you're not using lazy loading) you can create a small project with a main component which uses 2 different views.
In one case you create a single component for each view.
In the other you combine both views in one component.
Then build and serve both and you can see the difference in the weight of your JS files.
Hope this helps

How to optimize the rendering of components in Ember JS

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.

Web page div empty vs hide

When having 2 <div> elements both with fair amounts of graphic content and only one is shown at a time, is it better to hide then one not shown, or empty it and re-insert the html tags again?
When you hide, does everything stay in memory?
The answer is most probably: it depends.
As humans, we have some orientation around what's required in terms of performance for different operation, but in this case when you are not sure, best practice is estimate and benchmark. The idea is to understand what's the compromise in every method:
First, and easier, is benchmark the memory impact of your hidden div. Note that a hidden <div> is kept in memory, but is not rendered in page, thus having a smaller memory footprint than a rendered element. Measuring this can be easily done, even simply using chrome task manager. Check multiple changing between the two, and measure the memory footprint when using each method. Is is really as major as you expected?
The second, a little more complicated: measure the impact to reloading and re-rendering on your client's system, and on the user experience of your app. Best is to use a WEAK machine, and maybe even a slow connection. Measure the delay created if any, if not using code and reporting, at least by your feel, and try to measure cpu peaking and process slowdown if any. Switch between the divs multiple times, in slow and rapid manners. Does it still feel slick?
In this case, I tend to guess the memory footprint is much smaller than you assume, but that's just my experience. I believe hiding and showing will require less effort than emptying and reloading.
That said, I'm certain after doing both, It'll probably become very clear to you what's the correct method for you. Hiding if the memory footprint is small, reloading if it's so large as to be worth the slow of reloading. Only you can measure and figure where's the line.
Side note: When hiding, best practice is to use display:none;. This ensures elements are removed from the render tree, which provides better performance than opacity: 0; / visibility: hidden;, although if you need one of those for specific functionality use them. If you don't need the functionality, then use display: none;. Also note that jQuery's .hide() uses display: none;, so it's best practice. From jQuery .hide() documentation:
This is roughly equivalent to calling .css( "display", "none" )
Sources:
How Web Browsers Work: Render Tree Construction
jQuery documentation: .hide()
jQuery documentation: .empty()

Opinion on adding pre-styled class to a dynamically created element or adding stying there & then

In our web application, there are a lot of effects flying about. We are switching to creating as many elements dynamically, read: when needed, as possible.
Im curious about this technique I love using on elements, that is, creating a class with css styling in the style sheet, and then when the element is created with js, I merely add the class to the element to give it the styling I in the css file.
Is this really the best approach or would giving the styling in javascript (element.style = *) be better?
Note, memory is very important in our case so whichever uses less memory & rendering load would be better.
This depends on the case. If you have a set style for an element, which you just switch on and off, then adding/removing a class is the way to go. However, if you are consistently changing the style (i.e. in an animation) then modifying the style is better. In terms of memory, adding/removing classes would probably be more memory efficient.
Putting it in a separate stylesheet is usually considered best practice in terms of maintainability, separation of content from logic, all that good stuff.
But memory usage and render times, which you mention specifically as being very important to you, might be another matter.
You can use the web developer tools built into most modern browsers (e.g., Chrome Developer Tools) to try both approaches and profile for memory and render times. In Chrome Dev Tools, select Timeline, hit the record button at the bottom, load your page, do a few things on the page if that's relevant to you, stop the recording, and examine the memory usage and load time right there.
If your concern is animations, you may want to install Chrome Canary which has a third option (aside from Timelines and Memory) under Timelines that is something like Frames.

Categories