News for hackers. Stuff that matters.
Re:When does React re-render? Explaining rerenders and how t... by davedx on Wednesday April 29, 2020 @05:56AM (#23017357)
I agree with most of what you say, but your conclusion:

> Its paradigm is a beautiful one to develop with in most ways, but there is a significant price to pay in terms of performance.

I've worked with React on-and-off since around 2013. I can count on one hand the number of times that out-of-the-box idiomatic React code has incurred a significant price in terms of performance. The majority of my React apps just work, they just render fast enough by default. One time I've had to optimize it was when I had a React app that displayed a page of items from the database without any pagination: once it got to a few hundred items, it would indeed render very slowly. My optimization here was actually not to start memoizing or implement componentShouldUpdate -- it was to implement pagination and search in the app, because the UX was more important than rendering speed, and solving the UX solved the render speed.

I don't understand what kind of apps people are building with React that incur these significant rendering performance costs? I could understand it if you're building a realtime cryptocurrency exchange dashboard but I don't think most people are doing that?

Re:When does React re-render? Explaining rerenders and how t... by mhenr18 on Wednesday April 29, 2020 @06:51AM (#23017696)
I work on an app that edits and renders fairly complex indoor floorplans to SVG, all using React.

We deal with large hospitals and airports, so it's normal for us to have tens of thousands of components mounted at once - pagination isn't a viable solution for our purposes.

We've had to tap basically every optimization that React apps can do when managing large numbers of elements - however this has been worth it for us:

- We can use the same code to render interactive plans on the client, and to render to print-quality PDFs on the server - We can use the same framework in our UI and plan rendering

The downside is that it's more CPU intensive than alternatives like a WebGL renderer, but for now that's a tradeoff worth making.

Re:When does React re-render? Explaining rerenders and how t... by mncharity on Wednesday April 29, 2020 @03:32PM (#23023187)
> more CPU intensive than alternatives like a WebGL renderer, but for now that's a tradeoff worth making

Mixing traditional React with WebGL is another option. There's react-three-fiber[1], and custom/simpler hybrids are also possible. Though I've not tried server-side rendering.

[1] https://github.com/react-spring/react-three-fiber

Re:When does React re-render? Explaining rerenders and how t... by simion314 on Wednesday April 29, 2020 @08:26AM (#23018248)
IMO pagination is garbage UX, any sane GUI tookit can render more then 100 items on screen. Imagine you text editor or spreeadsheet viewer would have a limit of 100 rows. Sane GUIs don't create all this rows widgets from the start but use smarter techniques. From what I seen this technique is called now "windowing" but I knew it before by the name of "render item recycling"
Re:When does React re-render? Explaining rerenders and how t... by danShumway on Wednesday April 29, 2020 @09:13AM (#23018678)
> any sane GUI tookit can render more then 100 items on screen

Sure, but it's uncommon that I want more than 100 items on a screen in a webapp. Infinite scroll is not an antipattern, but it is something that people should be a little bit cautious of.

Users like context and clear anchors -- I like to be able to hit a back/forward button and know where I'll end up. I also like pages to load quickly and not make a ton of background requests on mobile connections, so if I can have an initial page load under a few megabytes at max, and can wait for the user to request data before loading it -- that's sometimes an attractive proposition.

Multiple search engines used to experiment with infinite scrolling and virtual rows, and as far as I know, most of the big ones went back to pagination, and I think it's because sometimes pagination is genuinely better UX, particularly when you're scrolling through a long list of blog posts or search results. Of course you can put thousands of elements in the DOM, and you can implement virtual scrolling if you need tens of thousands or millions. But the DOM tree is ultimately meant to be a human-traversable interface, and a <ul> element with several thousand <li>s beneath it is arguably not very traversable.

There are no hard rules here and there are a lot of caveats to what I'm about to say -- but I now bias towards avoiding DOM trees that are so big that I couldn't stick the current tree in a text editor and mostly consume its content textually, and that includes on dynamic web apps. The current state I'm displaying to the user should be small enough that the user can wrap their head around it.

The fact that React is so slow that you basically need to at least occasionally think about how you're rendering state is a separate conversation.

Re:When does React re-render? Explaining rerenders and how t... by simion314 on Wednesday April 29, 2020 @10:23AM (#23019600)
Not all lists have thumbnail with images, it could be a taqble with pure text, I think that doing a single request and grabbing 1000 rows of text and have it instantly accessible is much better then paginating it and doing the Next Page and loading screen etc.

I am not talking about infinite data here, but data that fits in one single request, that also fits in RAM but does not fit all at once as rendered DOM elements, so the fix is that the GUI widget for this table is smart and instead of rendering 1000 tables will not do that, will render just the visible part and the a few rows above and under the viewport, when you scroll the data in the table cels is changed and no new DOM elements are created. This should be soemthing that the developer should not think about, in this sane GUI toolkits you just do something like

widget.dataProvider =myData;

Edit:

Also for the case of youtube videos, you don't load "download" the thumbnails, those are just string, a sane toolkit will not load all those thumbnails until you bring them into view. I hate YT implementation, you get 3 rows of video then you scroll wait 2 seconds for next 3 rows to load, scroll again, wait again 2 seconds. You could have loaded the strings for all the videos, then lazy load the thumbnails when needed and skip the step of fetch me the next page of string after the strings arrive now fetch the images for those strings.

Re:When does React re-render? Explaining rerenders and how t... by TeMPOraL on Wednesday April 29, 2020 @09:35AM (#23018906)
> Sure, but it's uncommon that I want more than 100 items on a screen in a webapp. Infinite scroll is not an antipattern, but it is something that people should be a little bit cautious of.

Having ~100-200 items, I'd damn love to have them all on the screen. It seems like the best option out of the trio of render all, pagination or infinite scroll. Pagination is faster than infinite scroll, infinite scroll is more convenient than pagination, but both make it hard to reliably display data in sequence (as the whole data set isn't loaded immediately anymore) - and more importantly, both break search. However bad and bare-bones searching is in the browser, it's still better than search reimplementations in web apps, because the latter aren't any more sophisticated, and also have limited scope.

That's just my opinion, and a point of annoyance with modern SPAs. Most of the time when I have to scroll a lot, or traverse a bunch of pages, all I really want is to be able to CTRL+F for the thing I'm looking for without changing the state of the application.

Re:When does React re-render? Explaining rerenders and how t... by deckard1 on Wednesday April 29, 2020 @11:12AM (#23020184)
> it's uncommon that I want more than 100 items

I believe the discussion is GUI items, not what you might consider data items. Look at this current Hacker News page. Each comment, depending on how fine-grained you're counting, looks to have about 5-6 or more GUI components. In your browser viewport you may see a dozen comments. GUI components add up quickly. These are also only the components in view. React, however, is rendering the entire page. Easily hundreds of React components.

Re:When does React re-render? Explaining rerenders and how t... by danShumway on Wednesday April 29, 2020 @12:07PM (#23020818)
But depending on how they're styled and what animations you're using, React can easily handle rendering out 1000 DOM nodes.

To be clear, I don't want to act like it's not a real concern, I've been in situations where the number of DOM elements I was rendering out with React ended up being a performance concern. It's a real thing. Heck, I've been in situations where React's insistence on computing the virtual DOM was a performance problem. One of the downsides of component-based architecture is that it's very easy to get into situations where you're completely pointlessly duplicating effort parsing data multiple times and passing it around between components and mapping it to new lists of data. It's a major weakness for systems like React that encourage you to loosely couple all of your components, even components that are inherently very related to each other.

But I think people are underestimating what that component/DOM limit is, even for browsers like IE 11.

If you have 100 items on screen, and it's causing the browser to slow down, you'd better be doing something at least somewhat complicated with those elements. You'd better be sticking some SVG charts in there or something. Otherwise I'm going to (perhaps uncharitably) accuse you of overcomplicating your DOM and inserting a bunch of nodes that don't need to exist.

If someone wants to try and implement HN in React, they shouldn't be using 5-6 separate React components for a single comment, that's... I don't know how to parse that kind of architecture. I don't want to be dismissive about it, and different people have different approaches to programming -- but I feel pretty strongly that kind of granularity is over-engineering.

Re:When does React re-render? Explaining rerenders and how t... by simion314 on Wednesday April 29, 2020 @02:01PM (#23022164)
Not OC but from my experience because you have some nested DIVs and spans and some other node elements for each data item when you first load your data you get a big hang/freeze because the browsers are still slow at creating this elements, this is a browser issue I think, because most of the time you want to have a big list of similar items there should not be such a giant work of creating and computing similar DOM elements but I assume because of how complex css engine is you get this giant freeze.
Re:When does React re-render? Explaining rerenders and how t... by danShumway on Wednesday April 29, 2020 @02:54PM (#23022766)
Eh... you really shouldn't get a big hang/freeze if you're just talking about inserting 1000 nodes into the DOM. It's not going to be fast enough that you can do it at 60fps, but that's not the point of the DOM -- 60fps insertion is not something we care about.

I mean, yes, some of this is dependent on CSS. If you're doing complex rendering, or doing something strange with your fonts. I'm not going to make absolute claims about performance in every case, and different people have different interactions and requirements they're dealing with. There's caveats.

However, if someone comes to me and says, "I put 1000 DOM nodes into the browser and my page froze", I might not immediately make strong claims about the application, but I am going to immediately start looking around the codebase suspiciously to see if they're doing something strange or abnormal.

The current HN page you're on right now has ~2500 DOM nodes. Does it freeze for you when you load the page?

People complain a lot about DOM insertion, but while DOM insertion does sometimes cause problems, I've found it's more often that the problems happened before the insertion. At the point where DOM insertion actually becomes a problem, I suspect we're usually no longer talking about lists of 1000 simple table elements, or just putting 100 search results on a single page.

Re:When does React re-render? Explaining rerenders and how t... by simion314 on Wednesday April 29, 2020 @03:12PM (#23022937)
I am not sure what I did wrong, maybe if I had set some min/max height/width on soem elements it would have improved the performance, or maybe if i changed some flex-box property so regular layout or maybe if I changed some css rule on some parent somewhere it would have worked better.

I am sure I can make a list with just text and not css I can insert 1000 text nodes in it, the issue is if you have something mroe complex like a grid with thumbnails and titles, and a small description under, and some css effect for hover, and a few buttons when you hover over those items etc. In a sane GUI this 1000 widgets are not created at all, only the visible ones are created and when you scroll the data under the Widget is swapped, this is great because you don't have to focus on performance or use pagination and then pretend pagination is better UX.

Just to clarify I agree that there should not be many DOM nodes in a page, the browser or framework widget should be smart and transparently recycle the existing DOM elements, I imagine there would be some new List and Grid widgets that are more advanced but that could be used by everyone with his favorite framework.

Re:When does React re-render? Explaining rerenders and how t... by danShumway on Wednesday April 29, 2020 @03:32PM (#23023190)
> In a sane GUI this 1000 widgets are not created at all, only the visible ones are created

As a side note, this gets a little bit at an issue I feel pretty passionate about, which is that HTML is not a language for laying out interfaces, it is a user-facing interface itself. HTML isn't for programmers, it's for users.

The sane GUI you're talking about is essentially virtual rows, they're just baked into many native toolkits. A native interface doesn't insert everything because it doesn't have to, its interface is purely visual. If there are accessibility controls, they happen through a separate interface. If there are keyboard controls, they're based on the widget, not based purely on the content.

This is not a universal opinion, you will find people who disagree with me on this. But I think the web is fundamentally different than that. The web at least attempts to force your text interface and visual interface to be the same.

I'm not sure if it was to you or someone else that I mentioned that many apps (even native ones) are really just interactive documents when you think about their data separate from their styling. In my mind, the innovation of the web is that it acknowledges that, and it forces your interface to be a pure XML-like tree. And then you can put some styling on top of that with CSS if you want to. There are a few exceptions to that, but for the most part, HTML doesn't really let you hide a ton of information.

So imagine if you were building an app in GTK, and GTK said, "okay, first give me a pure-text representation of your interface that I can pipe to a terminal. And then I will allow you to position boxes on the screen, but only from the text that you told me I can pipe to the terminal."

That's a very different paradigm than how most other application frameworks work, and I think that the DOM's insistence of not having a lot of opaque data-bindings where possible makes a lot more sense when viewed through that lens. That lens also helps explain why some devs (myself included) got very annoyed about Google messing with that paradigm because they had their own 'cute' idea for web components.

The downside of this paradigm is that the tools you're talking about like data-bound lists aren't natively built into the DOM. You end up needing to use 3rd-party Javascript libraries for them. But for the most part, due to Javascript's popularity, those libraries are easy to find. Although due to Javascript's popularity, sometimes they are of dubious quality. :)

Re:When does React re-render? Explaining rerenders and how t... by simion314 on Wednesday April 29, 2020 @04:04PM (#23023520)
I understand, HTML is a document but it has this disadvantages and IMO if we want to use HTML everywhere we need some default Widgets for List and Table, don't change anything about current HTML but similar on how we have a Video or Canvas element we might want something for this uses cases and not force each developer re-invent the wheel. If is not built=int he browser I would like some sane JS implementation (framework independent and without any dependencies on 100 left-pads),

This thing where each developer re=invents same thing over and over and each implementation is broken in some way it bothers me, like the search input in Youtube has a dropdown with some suggestion, that dropdown popup can get stuck open until you reload the page, so even Google engineers are not capable of implementing a 100% working simple Widget.

Re:When does React re-render? Explaining rerenders and how t... by renke1 on Wednesday April 29, 2020 @09:17AM (#23018727)
Sometimes also called a virtualized list (react-virtualized is a popular implementation). Perfectly fine if keeping a lot items in memory isn't a problem (it rarely is). Of course fetching a lot of data from a backend can be a problem.
Re:When does React re-render? Explaining rerenders and how t... by nothis on Wednesday April 29, 2020 @01:12PM (#23021591)
>IMO pagination is garbage UX, any sane GUI tookit can render more then 100 items on screen.

Well, I guess that's the web in 2020 in a nutshell, lol. What would you do with a list of 100,000 items? Just slowly scroll them out, one by one while your scroll gets faster and faster? At one point, are you just a billion pixels down? What does "scrolling up" even mean down there? Or do we just limit all lists to 1000 items, period?

Re:When does React re-render? Explaining rerenders and how t... by simion314 on Wednesday April 29, 2020 @02:10PM (#23022284)
It depends on the application, should we limit text editors to 1000 lines?

Should you limit the files in a folder to some number because the ListWidget has a limit of 1000 ?

No, the solution is too use our brain and realize that you can open giant log files in a text editor , you can have a list with many items in, this problem were solved already the issue is that HTML was designed for documents not applications and the built-in lists or tables are not optimized at all, where a List widget or DataGrid Widget in other toolkits were optimized.

I am not expecting a developer to put some hard work to fix this in his app, browsers or frameworks should do this, I dislike the idea that pagination is good UX as an excuse for "pagination is the cheap solution"

Re:When does React re-render? Explaining rerenders and how t... by azangru on Wednesday April 29, 2020 @06:26AM (#23017547)
I saw in a recent tweet (can't find now) that React-based web apps were draining mobile phone batteries significantly faster than the comparison, because, with the constant re-renders, they were generating a heavier CPU load. This is something I had never thought about before.
Re:When does React re-render? Explaining rerenders and how t... by davedx on Wednesday April 29, 2020 @06:34AM (#23017592)
It makes sense, if it's changing very quickly and re-rendering the whole component tree -- say it's some kind of realtime stream of updates or a graphql subscription. And then of course you should try and optimize so only that component is re-rendered. My main argument is against people who try to argue that you should memoize a form input field or a div or something that changes once every few seconds or so. It's just pointless.
Re:When does React re-render? Explaining rerenders and how t... by runawaybottle on Wednesday April 29, 2020 @11:16AM (#23020236)
That app could be just as battery draining as a vue or angular app. We’d have to know the details.
Re:When does React re-render? Explaining rerenders and how t... by nothis on Wednesday April 29, 2020 @01:08PM (#23021539)
>I don't understand what kind of apps people are building with React that incur these significant rendering performance costs? I could understand it if you're building a realtime cryptocurrency exchange dashboard but I don't think most people are doing that?

I think it's just easy to make mistakes (bad loops, overly trigger-happy interpretations of "state change", etc), especially for all things "lists" (which make up half the web). Since people make mistakes, I'd always consider easy-to-make mistakes a design flaw, in this case affecting performance.

Also there's a psychological cost to making incremental "loading" operations visible. Although some mysterious "research" is frequently cited that people just fucking LOVE spinning loading icons and gray placeholder boxes that are never where the actual content will pop in, it's just instantly making my perception of a site slower. If a website just takes 5 seconds to load, okay. If, during that time, it just pops in and out 50 components, 3 different loading bars, spinning whirlies and blurry placeholder images (where the one I actually want to see always loads last), I'm suddenly having a "delay experience". It's like a whole firework of bullshit happening to remind you the site HAS NOT loaded yet.