The fact that there are debugging tools at the React level does reduce complexity. It means you don't need to understand the details of how React is implemented. You can just think in terms of React concepts (which are quite straightforward and have excellent documentation).
In React's defense, it's far from "impenetrable." In fact, its API exposes less than a dozen attachment points (considering render + lifecycle methods or their hook equivalents). It's a small and stable interface on top of a simple tree structure and an intuitive reconciliation algorithm. Most of the time you don't even need to reason about its logic, but when you do, it's understandable and debuggable.
I'm also skeptical that we should consider framework-specific dev tools as evidence of an impenetrable abstraction. As long as the tools strictly enhance the debugging experience, they are a feature, not a smell. They are evidence of a problem when they only exist because it's impossible to debug the API without them.
For example, Apollo Dev Tools "strictly enhances" the debugging experience. It provides a nice UI for GraphQL specific debugging sessions, but it doesn't break the "network" tab of Dev Tools. If you want to use apollo-client without its dev tools, you're no worse off than you were before adopting apollo-client. But you do gain something if you choose to use them.
Things just need to improve there, one way or another...
There are a million other JavaScript libraries that do not have this problem, for what it's worth.
> It means you don't need to understand the details of how React is implemented.
Isn't this the topic of discussion? Why shouldn't it be as simple as "React stores state in this variable" and I can just poke at it like any other variable?
Abstractions are great, but they all leak eventually. Being able to see through the abstraction is immensely valuable, regardless of where you are in the stack.
Don't confuse simplicity for its pernicious cousin convenience, which usually does not actually reduce complexity, but heralds it.
It's a library, but it does provide a runtime. As such it IMO makes sense that it would have it's own debugging tools. This is pretty common for complex frameworks. Other frontend frameworks like Angular and Vue do it. As do backend frameworks like Rails and Laravel. Or as another example you could look at Unity (the game framework).
You can still use the JavaScript debugger, and I do all the time with React code. But for React specific concepts the React specific tools provide a better experience.
> Why does React go though so much effort to obfuscate its internals to such an extreme? There are a million other JavaScript libraries that do not have this problem, for what it's worth.
It doesn't do it intentionally. It's internals are somewhat complex for performance reasons. Which other JavaScript libraries allow you to inspect their current state with the JavaScript debugger? That's what the React dev tools give you: state inspection. IME, lot's libraries make inspecting that quite difficult (unless they're using global variables).
> Why shouldn't it be as simple as "React stores state in this variable" and I can just poke at it like any other variable?
The problem is that you can't typically poke variables using the JavaScript debugger. To do so you need to get a reference to the variable. And you can only reasonably do that for globals.
> Abstractions are great, but they all leak eventually. Being able to see through the abstraction is immensely valuable, regardless of where you are in the stack.
I guess I've just never hit into the limitations of the React abstraction (and I've done pretty complex things). Nor have I ever hit a bug in the implementation. To me it's like my database or my filesystem: sure it's great to be able to peak under the hood if I really need to, but 99.9% of the time I'm super glad that I don't. I've had much worse experiences with Angular (1 and 2) where I frequently felt like the abstraction was leaking a lot.
(tl;dr: lol)