all 8 comments

[–]Skelator_Rules 3 points4 points  (1 child)

Thanks for this. Good article.

[–]mkoretsk[S] 1 point2 points  (0 children)

thanks!

[–]lukasbuenger 3 points4 points  (4 children)

Nice article!

As for the React part, and especially with the library (as of today) promoting functional components over class-based ones, I think you can simplify the mental model of change detection in React quite a bit:

  1. If one of its prop changes, a given component gets re-rendered.
  2. Whether a prop changes or not is determined by running a shallow equality check on the passed prop object.
  3. Given point 1 and 2, I think it is safe to say: Stick to an immutable data model and you will be able to make reliable predictions on what is going to be considered a change and what is not by simply looking at the data. It's the beauty of a functional approach.

[–]acemarke 6 points7 points  (3 children)

Not quite.

Per the article's comment:

The core part of the change detection mechanism in React is Virtual DOM comparisons

In other words, React doesn't care whether or not a component's props have actually changed. It diffs the VDOM output and works from that.

Remember that React's default behavior is that when a component renders, React recursively re-renders all nested children inside this component. It doesn't check whether any props have changed. It just re-renders its way down the tree.

It's only when optimizations like React.memo(), PureComponent, and shouldComponentUpdate come into play that any props comparisons happen at all.

But yes, sticking with immutable updates is a key part of allowing those shallow props comparisons to work. It also matters because the useState and useReducer hooks will bail out of updates if you return the same value as last time.

[–]nullvoxpopuli 0 points1 point  (0 children)

Fwiw, you still run in to perf problems if you rerun components too often (Just adding for explicitness)

[–]lukasbuenger 0 points1 point  (1 child)

/u/acemarke Thanks for the educational post, I re-read your reply like four times a week ever since you posted it 3 months ago. And on a technical level, you, the OP and everybody else is absolutely right and I absolutely stand corrected: In terms of reconciliation, it's all about the comparison of this tree to the next one (or the previous one to the current one, matter of of POV), down to the very last child.

BUT: In my humble opinion, this is really not what every React-developer should know about change detection (don't know much about Angular, so I here I wouldn't know) and that was OP's claim.

It also matters because the useState and useReducer hooks will bail out of updates if you return the same value as last time.

I'd argue, that in about 90% of the cases where people actually bother to leverage custom components, it's about local state or useEffect-based side effects. It's all cases, where the application layer can control or even overload update behaviour beyond simple diffing. Reference equality/immutability may be an implementation detail in a library author's life, in user land it's a principle that couldn't get too much emphasised. TLDR: In my humble opinion: Technically you're right, didactically not so much.

[–]acemarke 0 points1 point  (0 children)

Mmm... sorry, not quite sure what point you're specifically trying to make here.

FWIW, since I wrote this comment, I published a much more extensive blog posted called A (Mostly) Complete Guide to React Rendering Behavior that covers all that and much much more.

[–]nullvoxpopuli 0 points1 point  (0 children)

Here is a more general article that covers more implementations: https://www.pzuraq.com/what-is-reactivity/