> The web being the vast platform that it is and JavaScript eating so many domains may very well be a situation where not having full mastery of a language will still get you very far perhaps
Sure, it gets you into a project far enough to commit a lot of resources to it, and then falls over.
> So, perhaps the issue Heyer is lack of education, not that the ecosystem itself is unquestionably broken?
The problem may be a lack of education, but that becomes a problem with the ecosystem when the uneducated are determining the direction of the language. Classes are a feature of JavaScript now: that's irreversible damage done to the language. We can educate people about prototypical inheritance and explain to them why hacking classes over top of them is a bad idea, but that's too little too late: we can't remove classes from the language because there's already too much code that depends on them. And we can't even add classes into linters and say "don't use them", because as another commenter pointed out, core language features now depend on it. At this point, we have to embrace the suck.
And there's a fundamental opposition in the JS community to education. Education starts with admitting you don't know something, and you can see in this thread a lot of people jumping in to defend the JS ecosystem. But the type of defenses you see are telling: instead of discussing the technical merits of the decisions made, people are shooting the messenger[1] or taking it personally[2]. The only defense of JS that's vaguely technical is brundolf's post, which isn't so much a defense of JS as a strategy for writing good code in a crappy language. Not a single post here is actually defending the JS ecosystem on technical grounds.
> Also, curious, how do you handle state full actions without some kind of global? Genuinely curious
Let's say you are writing a configuration interface for virtual servers. You have three attributes on sliders bars: memory units, CPUs, and solid state drives. There's also a total cost field. The Redux global state way looks something like:
1. Have the CPUs, Memory Units, SSDs, and Total Cost in a global store.
2. Create 3 actions and corresponding reducers that update the Total Cost when any of the slider bars change.
3. Create 3 slider bar components, which dispatch to the global store with the proper actions.
4. Create a base component that renders the whole thing.
This approach already runs into some problems:
1. First, you've got three slider components that are basically the same. You can pull out the rendering code into a Slider superclass, and that reduces the repetition, but your reusability is limited: every time you want to add a slider elsewhere in the app you have to write a whole new component. And when you look at those components, you've got a lot of implicit code being pulled in by the superclass, which means you have to switch between the component and the supercomponent to understand what's going on.
2. Your reducers operate on changes in different pieces of data, but ultimately each all have to know about all three data sources to calculate the total. You can check out "Reusing Reducer Logic"[3] and that's certainly a better idea than repeating yourself three times, but you can see that there's a complexity explosion happening here.
3. In actuality, what happens too often is the duplication is just left in the three slider classes, and you have three reducers since reuse is too complex. Even if you're very disciplined about it, the complexity of achieving reuse sometimes mean you don't have time or energy to do it. In short: this design punishes reusability and rewards duplication.
4. If you want to have multiple private servers, you now have to change literally every single one of these components, because every single one needs to know in some way which server it's operating on.
Let's design the same functionality, without Redux:
1. Have a slider component which accepts a min, max, initialValue and onValueChanged callback as props.
2. Have a parent component that holds the three values in its state, and renders the three sliders with onValueChanged callbacks that update the parent component's state. The total can be rendered without being stored in state, but if you want to have multiple servers on the page, you might want to put the total in state.
At first glance, each of these components is slightly larger, and it seems annoying to have to pass all the info into the slider components. But consider the benefits:
1. All your server state is in one place. No one else stores information on servers, and nowhere else even knows that servers exist. It's decoupled.
2. Because of this decoupling, the slider is a reusable component. You can use the same slider to modify literally anything with a min/max/value, favoring composition over inheritance[4].
3. The only thing you have to understand here is React components. The complexity is greatly reduced.
4. If you want to have multiple servers on the page, the parent component is already most of the way to being a reusable component. All you have to do is expose props for the initial server configuration, and an onServerChanged handler. There's one gotcha here: changes to the sliders need to propagate up to the parent of the parent component and still trigger the proper events and re-rendering. Pitfalls can be avoided here by using an immutability library--I prefer Immer, but I imagine ImmutableJS can do the same things. You could even roll your own, since you really don't need much to handle this--a simple set of copy-on-write functions would be adequate, although they would stop being performant if your data structure gets more complex.
[1] "This sounds like the sort of thing I hear from folks who have only passively dealt with the Javascript ecosystem"
[2] "Almost every comment thread, regardless of topic, has someone shitting on front-end developers and it's extremely demoralizing."
[3] https://redux.js.org/recipes/structuring-reducers/reusing-re...
[4] https://en.wikipedia.org/wiki/Composition_over_inheritance