(Replying to PARENT post)

This is a wonderful example of a well engineered solution to the wrong problem. React is a wonderful view library, and if limited to that use it is remarkably fast and easy to use.

But the usual way of building things is to treat React as a total web app framework. The terminology is very confused: they still call it "rendering", even though it now usually includes data fetching, complex manipulations, event processing, etc. You just `React.render` once when your page first loads and then child components take care of the rest. It should really be called `React.start`.

> The reason for the stutter is simple: once rendering begins, it can’t be interrupted.

Rendering should never need to be interrupted. If your app is architected to have any rendering operation take long enough that it's perceptible to the user, STOP DOING THAT THING DURING RENDERING.

Want a performant web app? Apply separation of concerns properly, and limit your use of React to the view layer.

πŸ‘€couchandπŸ•‘6yπŸ”Ό0πŸ—¨οΈ0

(Replying to PARENT post)

> React is a wonderful view library

The React model makes sense because of how state management is part of it, not strictly just the view. I think seeing it just as a view library necessarily leads to the rest of your other conclusions. I recommend reading https://overreacted.io/react-as-a-ui-runtime/ by Abramov which describes React as a UI runtime.

Embracing React as a UI runtime you eventually find problems that concurrent mode solves. Some are related to performance and concurrency, but some are related to managing state and data dependencies. It also provides idiomatic ways that encourage good UX (like managing error/loading conditions once, at the right level).

πŸ‘€kiliancsπŸ•‘6yπŸ”Ό0πŸ—¨οΈ0

(Replying to PARENT post)

> If your app is architected to have any rendering operation take long enough that it's perceptible to the user, STOP DOING THAT THING DURING RENDERING.

At my workplace we frequently encounter cases where the rendering itself - just the evaluation of the pure React functions - takes hundreds of milliseconds, if not several seconds. This is after memoizing every part of it that can be memoized, after profiling it for places where work can be shaved off, etc. Sometimes there really is just that much rendering, and unlike other types of computation, today's React gives you no options for putting that in a worker or breaking it up. Tabs' single threads mean you can't even scroll in the interim. Concurrent Mode is the only hope we have of solving that case, other than avoiding it with paging, which is what we currently do.

πŸ‘€_bxg1πŸ•‘6yπŸ”Ό0πŸ—¨οΈ0

(Replying to PARENT post)

Out of curiosity, how is it not still "rendering"? Do you prefer "start" because it renders a tree of children?

But yes, rendering doesn't need to be interrupted. They specifically mention architecture decisions to avoid rendering operations that take too long (debounce and throttle).

This eliminates previously necessary architecture decisions while providing a better user experience. How is that solving the wrong problem?

Also, this is still the view layer. There's nothing React-specific about data fetching, "complex manipulations" or "event processing".

Previously if you had a text input whose output you used to fetch some data and render in a list, you'd use debounce.

Now, with Concurrent Mode, you don't have to and can instead use the React API.

πŸ‘€nickdandakisπŸ•‘6yπŸ”Ό0πŸ—¨οΈ0

(Replying to PARENT post)

>Apply separation of concerns properly

With the component paradigm, these things can't always easily be separated. Or, it is useful to consolidate data concerns and UI concerns, but often data concerns like UI have a hierarchy, or the concerns are spread all over the place (not in neat, clear groups).

It is very useful to declaratively specify the recipe for both UI and data, and allow the framework to coordinate these things across and within components.

>Rendering should never need to be interrupted.

Following this line of thought would lead to not rendering anything until everything is ready. Large applications have multiple levels of components and data concerns. These solutions allow for isolating responsibilities at smaller levels, and coordinating their presentation in ways that produce good UI (few loading spinners, flickering etc).

>and if limited to that use

This simply passes the responsibility somewhere else no? And any significant apps can't avoid these concerns. You'd still be left with the coordination between React and whatever else was handling these concerns, but with much more code likely to tie them together.

πŸ‘€PKopπŸ•‘6yπŸ”Ό0πŸ—¨οΈ0

(Replying to PARENT post)

> Apply separation of concerns properly

The disconnect here is the definition of "concerns."

One analogy is, imagine cutting a square into stripes. You're implying that there's only one way to do so, say, cutting horizontally. But you can easily cut vertically and still end up with well separated stripes.

The stripes, whether horizontal or vertical, are separated cleanly.

While you may see splitting by data fetching, view, etc. as the only way to separate by concerns, there are certainly others. The component model that has been adopted by many React users is one such way.

πŸ‘€bcynπŸ•‘6yπŸ”Ό0πŸ—¨οΈ0

(Replying to PARENT post)

> If your app is architected to have any rendering operation take long enough that it's perceptible to the user, STOP DOING THAT THING DURING RENDERING.

As is tradition, frontend developers are still slowly reinventing the techniques from other fields.

The neat thing about UI is that your end user is a human and a human can't visually process too many items at once on a screen. This means you should never really need to consider more than O(thousands) elements to render either. That should always fit under 16ms.

This has been known to game developers since forever. Don't spend resources on things that won't be displayed. If you are doing too much work that means you aren't culling invisible objects or approximating things at a lower level of detail.

In practice for frontend developers, this just means using stuff like react-virtualized so that even if you have a list of a bajillion objects, only the stuff in the viewport is rendered.

πŸ‘€throwaway_badπŸ•‘6yπŸ”Ό0πŸ—¨οΈ0

(Replying to PARENT post)

> They still call it "rendering", even though it now usually includes data fetching.

Their documentation explicitly states that Suspense is not for data fetching. That's what the new Relay APIs are for.

https://reactjs.org/docs/concurrent-mode-suspense.html#what-...

πŸ‘€leerobπŸ•‘6yπŸ”Ό0πŸ—¨οΈ0

(Replying to PARENT post)

The browser gives you 16ms to execute JS if you want to avoid stutter. Even with the tightest, hand rolled, vanilla JavaScript there are plenty of situations where that isn't enough time, especially on low end devices.

Seperation of concerns is all good and well, but there are some product experiences you simply can't do with plain HTML.

πŸ‘€underwaterπŸ•‘6yπŸ”Ό0πŸ—¨οΈ0

(Replying to PARENT post)

There's nothing inherently special about rendering. If the function is an unresolved promise then it should automatically await, and treat that component as blank or nonexistent. It's just legacy architecture to make render functions sync and blocking.
πŸ‘€manigandhamπŸ•‘6yπŸ”Ό0πŸ—¨οΈ0

(Replying to PARENT post)

Without data fetching or manipulating, you have nothing to render.
πŸ‘€MuffinFlavoredπŸ•‘6yπŸ”Ό0πŸ—¨οΈ0