Really? What caveats?
The only maybe oddity that I can think of is that if the deps array is omitted it always runs.
What API would you prefer? Something more like signals?
Really? What caveats?
The only maybe oddity that I can think of is that if the deps array is omitted it always runs.
What API would you prefer? Something more like signals?
useEffect breaks the sequential nature of your code and makes it feel like you're reading a script from a Quentin Tarantino movie.
Sequential, blocking modells like i.e. batch ETL jobs are just not the domain of the browser.
The DOM is almost entirely sync, all the operations on it are blocking operations (including things like replacing an entire document with innerHTML).
Thing about async/await.
const a = await doThing();
const b = await doOtherThing();
The order of the written code and the order of the executed codes are two different things. Being able to write code in proximate/logical order is a enormous relief, even if things don't actually happen like that.Same with hooks.
function SomeComponent({ someProp }) {
function doStuff() {
// do stuff
}
useEffect(doStuff, [someProp])
}
This trivial example is easy to read, but as more state and effects get added to a component, it quickly becomes fairly cumbersome to figure out the exact order in which your code runs.I recalling using a lot of useRef to manually tune when to re-render, and in an ideal world I shouldn't be this granular about it.
You can certainly use one of the many React map wrapper libraries to lessen the pain, the pain is still very real, just dealt with by someone else.
Hooks imo are great, as they are pretty explicit and low level.
Nowadays signals are the new kid on the block, though mobx and similar have existed since forever in react land, but they have their own crazy edge cases like reactive loops and implicit behavior.
>But I don't think the "pretend it isn't" makes any sense
Well, let me expand a bit more. React's pitch is that view is a function of state, and essentially designed around the idea of an immutable state which re-renders everything when changed. It then offered some APIs to allow fine-tuning of rendering via hooks which either ties with data changes or some rendering life-cycle. To me the API screams of stubborn refusal to let go of the "view as a function of state" mantra: When you encounter a scenario where it breaks the mantra, lets add another lever to handle it. This lever also has to be pulled by you the developer, and it is up to you to know when to do it.
>I actually like React more than Svelte for many reasons, but magic compilers and templates are two big ones.
I don't really have an issue with compilers. They are the accepted magic that bridges between language for people and language for machines. The ideal language might be something that is functional and immutable language that it is easy for us to read, but compiles to the optimized, imperative updates that machine can run well.
I'd probably like React better if it had a compile layer on top of its more functional parts?
As for templates, JSX is probably the one great thing that came out of React. It is no wonder that many other frameworks are embracing JSX, but none of them are really forking the idea of hooks.
Lifecycles existed since the first version, and they were always absolutely critical. Hooks just fixed many of their issues and made them more elegant, composable, and simple to write.
If it quacks like a duck..
Hm, could you give an example of this ideal performant state management world? Angular? Vue? Svelte? MobX?
As another commenter mentioned, yes it's less low level than managing your own dependencies, but then again, most React apps are already wrapped in layers and layers of abstractions/context providers/selectors and use Jest as their test runner (which injects the global namespace with functions) and does other black magic and weird metaprogramming, so I think most React devs are already OK with less lower level stuff.
> What API would you prefer? Something more like signals?
Yes. Or full tree redraws like Mithril.js did 8 years ago.
useEffect is for side-effects.
Either way, this is different than what I mean with Mithril.js (it does full tree re-renders on event handler calls or when a manual redraw function is called).
I don't really agree with this except to the extent that, sure, it would be ideal for all APIs and indeed the entire syntax of your programming language to be so well-designed that you don't need any lint rules to catch common mistakes. I'd love it if my static type checker could catch most mistakes like this (although the boundary between linting and static type checking is fuzzy).
But in practice, you're almost certainly going to either 1) have a linter or 2) have strong resolve that you will not make any easy mistakes that a linter could catch. And if you're in the second boat, it doesn't make sense to single out this particular easy mistake, given that omitting arguments is always an easy mistake to make in JavaScript.
Which linting rule?
> That being said, I'm not sure that an API is well-designed if the only way to use it effectively is by forcing you to even know there is an eslint plugin to begin with, and then once you do know that, that means now you're being forced to add eslint to your project whether you like it or not. And sometimes eslint just stops working for who knows what reason, I have a developer on my team who's constantly dealing with issues where his eslint/prettier setup isn't running correctly.
Yes, not to mention eslint is slow with large codebases. Fingers crossed for the Rust(?) rewrite.
The only downside is that sometimes, the rule can end up being overly aggressive and tell you to add things which you explicitly don't want in your dependency array, but it's helpful probably 95+% of the time and not hard to opt out of or work around as needed.
As you already mentioned, it's not a silver bullet.
In my opinion if people have the rule installed and still feel the need to disable it then it shows there may be an issue with the API itself. This is coming as someone who has written React for a living since before even ES6 classes were supported.
I see it relatively often, including in production codebases where people just disable the rule because they don't know how to write the sometimes non-intuitive way to get around it.
- Don't use effects for things that aren't genuinely effectful
- Put finnicky state management stuff in reusable utils instead of re-implementing it from primitives over and over again.
Neither is React-specific.
That's a bunch of examples where there are good alternatives.