Live data from Hacker News

Why React Re-Renders

joshwcomeau.com

71–80 of 168 posts

Re: Why React Re-Renders

#71

Earlier quoted context omitted.

Yeah, this is not to belittle the complexity of React under the hood. But they are functions, and it seems you can assume they will be called in a straightforward manner when they render (whether they are invoked as explicit function calls or via returned JSX). The only real complexity (for the developer) is the use of hooks, effects etc. if you don't mess with useMemo (which you generally shouldn't). Certainly they…

> if you don't mess with useMemo (which you generally shouldn't) why? is this not the primary way to re-init expensive internal component state when specific props change?

He touches on this in the piece briefly.

> I think as developers, we tend to overestimate how expensive re-renders are. In the case of our Decoration component, re-renders are lightning quick.

Certainly it's there for a reason, and you may have expensive operations, but in my experience developers reach for useMemo much too early and often, and it just adds complexity to their functions. The cost of checking the parameters for changes adds overhead that may be more expensive than just re-doing the "expensive" operation. My rule of thumb is if the operation is less than O(n) where n There have been some benchmarks done on this, and when it pays off to use.

Re: Why React Re-Renders

#72
post #48

Earlier quoted context omitted.

> How do they onboard new members to their terrible setup, one might wonder? I can't speak for the specific companies you listed, but the number of times I've heard someone sing praises about a homegrown UI framework at their place of employment is approximately zero. The sentiment expressed about those is generally hatred and agony. That's not to say it can't be done well, but most don't. Also, a company being able…

> a homegrown UI framework I am deeply puzzled by both your and the sibling comment, which suggest that the only way to go is to build a framework. To advance such argument, especially when comparing something to React, is to forget that: - React also for a long time was advertised as a view-layer library for creating UI components, not as a "framework". - There've been numerous debates in which advocates of Angular…

Problem is, Web Components still don't support reactivity and passing complex props, so you need a framework anyways, and at that point it might as well be React.

I've seen people do abominations like each web component is a React root, message passing systems on the side for complex objects... better use React directly

Re: Why React Re-Renders

#73
post #54

Josh's content is always very very high quality. I look forward to him releasing his online React course [0] so that I can recommend it to others who are starting out. My personal biggest not-total-comprehension is around Hooks / effects. I've followed tutorials, used them in production, etc. I'm comfortable using them but I also consider them a bit of a black box, which I don't like (e.g. I'm not sure how they're im…

> e.g. I'm not sure how they're implemented It might help to have a simple mental model for them? Picture there is a global variable called _currentComponent: _currentComponent: { previousValue: React.Element hooks: HookValue[] currentHook: number firstRender: boolean } Each HookValue is whatever that hook wants. For useState something like: HookValue = { hookName: 'useState', value: [state, setState], } Before your…

Thank you for posting this.

Re: Why React Re-Renders

#74
post #48

Earlier quoted context omitted.

> How do they onboard new members to their terrible setup, one might wonder? I can't speak for the specific companies you listed, but the number of times I've heard someone sing praises about a homegrown UI framework at their place of employment is approximately zero. The sentiment expressed about those is generally hatred and agony. That's not to say it can't be done well, but most don't. Also, a company being able…

> a homegrown UI framework I am deeply puzzled by both your and the sibling comment, which suggest that the only way to go is to build a framework. To advance such argument, especially when comparing something to React, is to forget that: - React also for a long time was advertised as a view-layer library for creating UI components, not as a "framework". - There've been numerous debates in which advocates of Angular…

Was going to say the same as sibling @ReadTheLicense, but further Web Components were started before React so the idea that they are more modern isn't true.

Re: Why React Re-Renders

#75

Earlier quoted context omitted.

Yeah, this is not to belittle the complexity of React under the hood. But they are functions, and it seems you can assume they will be called in a straightforward manner when they render (whether they are invoked as explicit function calls or via returned JSX). The only real complexity (for the developer) is the use of hooks, effects etc. if you don't mess with useMemo (which you generally shouldn't). Certainly they…

> if you don't mess with useMemo (which you generally shouldn't) why? is this not the primary way to re-init expensive internal component state when specific props change?

GP's claim is a little too strong, but in my experience most uses of `useMemo` / `useCallback` are only necessary because people define things in the wrong scope, or write giant spaghetti components with 15 different props and no internal structure. The best memoization technique is not calling things repeatedly in the first place.

Re: Why React Re-Renders

#76
post #57

Earlier quoted context omitted.

Hooks feel like a good system that stopped right before it became pretty. Like, an componentDidMount event is a now useEffect with no second argument? But a componentWillUnmount event is now a useEffect, with no second argument, that returns a callback? It's powerful, and it's not that hard to use, but it's cryptic and random. Why call it useEffect instead of some other more meaningful phrase? I mean, "componentDidMo…

I love hooks, but I think they made a few mistakes. The weirdness around useEffect having different behavior with no second argument vs [] is one of them. And they should have included a useUnloadEffect() by default, even though it's trivial to write, just for clarity. It's way too easy to miscount the number of ()s in useEffect(() => () => {}, []); They also should have included a few other basic hooks, like useStab…

useRef is useStableValue

Re: Why React Re-Renders

#77
post #54

Josh's content is always very very high quality. I look forward to him releasing his online React course [0] so that I can recommend it to others who are starting out. My personal biggest not-total-comprehension is around Hooks / effects. I've followed tutorials, used them in production, etc. I'm comfortable using them but I also consider them a bit of a black box, which I don't like (e.g. I'm not sure how they're im…

> e.g. I'm not sure how they're implemented It might help to have a simple mental model for them? Picture there is a global variable called _currentComponent: _currentComponent: { previousValue: React.Element hooks: HookValue[] currentHook: number firstRender: boolean } Each HookValue is whatever that hook wants. For useState something like: HookValue = { hookName: 'useState', value: [state, setState], } Before your…

Yep! Also see Shawn Swyx Wang's talk "Getting Closure on React Hooks", where he goes through an equivalent example in more detail:

https://www.swyx.io/hooks/

Re: Why React Re-Renders

#78
post #56

A pain point with React is large data structures. To re-render (assuming class components), you can setState with the changed property. For example if your state has two properties named foo and bar, and bar has changed then you call setState({ bar: newValue }). This works if you have simple properties. What if you have large complex data structures, and you need to modify a property deep down inside? Then you can ma…

> But it is tremendously wasteful to make a complete copy of a large data structure!

You don't make a complete copy: you make a shallow copy of the spine, and then only descend along the fields you actually modify. The number of operations scales as O(branching factor * depth), not O(size).

Re: Why React Re-Renders

#79
post #57

Earlier quoted context omitted.

Hooks feel like a good system that stopped right before it became pretty. Like, an componentDidMount event is a now useEffect with no second argument? But a componentWillUnmount event is now a useEffect, with no second argument, that returns a callback? It's powerful, and it's not that hard to use, but it's cryptic and random. Why call it useEffect instead of some other more meaningful phrase? I mean, "componentDidMo…

I love hooks, but I think they made a few mistakes. The weirdness around useEffect having different behavior with no second argument vs [] is one of them. And they should have included a useUnloadEffect() by default, even though it's trivial to write, just for clarity. It's way too easy to miscount the number of ()s in useEffect(() => () => {}, []); They also should have included a few other basic hooks, like useStab…

It seems like almost always if you want to do anything during unmount, it's cleaning up something you set up in a useEffect call, which you also want to do any time the useEffect call's dependency list changes, so it being part of the useEffect hook helps programmers fall into the pit of success. React's older class-based components had the unmount handling separate (componentWillUnmount), and in my experience on a large React codebase, many if not most components using componentWillUnmount were subtly flawed and failed to handle certain cases where props or state updated in a way that should have caused effects to be cleaned up or adjusted. React's useEffect hook way of grouping up effects with their own cleanup code helps people handle these cases correctly even without realizing it sometimes.

Re: Why React Re-Renders

#80
post #56

A pain point with React is large data structures. To re-render (assuming class components), you can setState with the changed property. For example if your state has two properties named foo and bar, and bar has changed then you call setState({ bar: newValue }). This works if you have simple properties. What if you have large complex data structures, and you need to modify a property deep down inside? Then you can ma…

FWIW, React has always been designed around some Functional Programming type principles, such as immutable updates. Immutable updates do in fact require that if you want to update `state.some.nested.field`, you have to make copies of _all_ objects in that path: `nested`, `some`, and `state`. This isn't unique to React. Yes, class component `this.setState()` lets you get away with mutations. That's not really a _good_…

When updating deeply-nested immutable objects, the Immer library is great. You call the `produce(immutableValue, draft => { ... })` function with some immutable value and a callback function that manipulates a mutable proxy object mimicking the immutable value, and then the function returns a new immutable value with the same changes made by the callback function. The mutable proxy object never escapes the callback, so the use of Immer stays self-contained as an implementation detail of your code without infecting your component's public API or anything.

Another alternative is the "immutability-helper" library, which was originally published by the React team as "react-addons-update". It's a lighter library with less proxy magic going on, but at the cost of being more explicit: instead you create an object describing how to update an immutable value to produce a new immutable value. I've used it in the past in a few places but mostly recommend Immer over it now.

Post reply on HN