You can split the first example in small functions and it'll still be a mess. The post is not about duplication, function size, or nesting. We gained predictability by preventing _accumulation_ of errors — which we got by always restarting rendering from scratch.
Well- the React example doesn’t really restart rendering from scratch (as you yourself mentioned). And in larger applications you’d still prefer to not ‘redraw from scratch’ in React either and build on top of a previous setup.
Really what you’re doing is preferring more declarative programming practices over procedural. And as a consequence, more declarative APIs like React.
For the app developer, React code _does_ restart rendering from scratch. You have no access to the past rendered state from the render method (at least if you don’t intentionally escape the declarative model). This isn’t true only for bugs in React.
What happens internally in React is another question. But the point of React abstraction is to let _you_ think in terms of “render from scratch”.
I'd go one step further and say it is about encapsulation and no side effects. And one of the biggest benefits is that you take the time when the problem space is modeled in your head to break it into its small solvable pieces. When you go back to refactor, don't just jam more code into function A. Refactor it to support the new use cases with new encapsulation.
How many states can a selection of random, non-expert humans interacting with your code across a bevy of platforms encounter? The answer is always: Infinite.
Hand your application to a bunch of people that are completely ignorant of your intentions and it will reveal a seemingly endless bevy of code paths you didn't think we're possible! It will also reveal entire categories of code paths that have yet to exist but should!
In my TODO list I have a book idea... All I have is the title, "ERROR: This should never happen."
An advice that is valid since forever.