News for hackers. Stuff that matters.
Re:useStateMachine: A ½ kb state machine hook for React by Waterluvian on Saturday May 22, 2021 @07:43AM (#27245575)
I can't get over how amazing hooks are and how resistant I initially was to them.

They encapsulate logic so well and do an amazing job being this isolated data/event source.

I find that I reuse them far more than I reuse components.

Re:useStateMachine: A ½ kb state machine hook for React by judofyr on Saturday May 22, 2021 @08:33AM (#27245895)
Interesting. I have the opposite experience, the more I use them the more clunky they feel.

* If there’s only useState, then everything is mostly fine. All is good.

* To avoid unnecessary re-rendering you’ll have to move callbacks into useCallback. These callbacks then also need to specify all of their dependencies. So many lines of code that are merely noise.

* They encourage having state locally in the component which often breaks down the moment you slightly tweak the design. So much refactoring!

* Dealing with any other (callback-based, stateful) API is confusing. If you want something to execute once initially you can use useEffect with an empty dependency list, but note that then there’s no way of accessing updates values (in callbacks) and everything will reflect the initial state. Often you’ll have to use useRef just to keep track of the current state. Or maybe useState?

* Debugging is painful. You forget one value in your dependency list and the weirdest things happen. Suddenly you have callbacks running in different rendering scopes with different values.

They feel very “brittle”: Once it works the code looks pretty, but when there’s a slight change of requirements you need to rethink everything.

Re:useStateMachine: A ½ kb state machine hook for React by deergomoo on Saturday May 22, 2021 @09:10AM (#27246161)
> To avoid unnecessary re-rendering you’ll have to move callbacks into useCallback. These callbacks then also need to specify all of their dependencies. So many lines of code that are merely noise.

I really like Vue 3’s Composition API as a much easier-to-use (IMO) implementation of hooks.

It’s conceptually very similar to React Hooks, but the method that defines them only runs once, when the component is instantiated. So straight away that removes any worries around conditionals and loops.

Instead of a plain value/object and an update function, the “hooks” instead return a reactive object that tracks it’s own dependencies (which are also all reactive objects). That removes any need to manage dependencies yourself, or for any memoization.

The only downside is that because a plain value (like a number or something) cannot be reactive, it has to be wrapped in an object and accessed via a “.value” property, but this is only relevant in the setup function. Anywhere else, like the Options API or in the template, accessing the value like a value will just get transparently proxied to the object.

Re:useStateMachine: A ½ kb state machine hook for React by nightski on Saturday May 22, 2021 @11:11AM (#27247268)
The entire concept of reactive objects brings back memories of extreme pain from KnockoutJS days (and terrible performance in complex scenarios to boot). I prefer just working with plain old data structures.
Re:useStateMachine: A ½ kb state machine hook for React by benatkin on Saturday May 22, 2021 @11:56AM (#27247710)
I prefer working with just plain old setup functions, that are called once.
Re:useStateMachine: A ½ kb state machine hook for React by bobthebuilders on Sunday May 23, 2021 @12:49AM (#27252539)
I find React and Vue to be different expressions of the same core concept in a way. Althoguh I do prefer the functional nature of React, reactive objects are a lot less boilerplate, even if it might be a bit slower. The composition api itself is actually I think where it shines, because the options API is very mediocre in my opinion.
Re:useStateMachine: A ½ kb state machine hook for React by yurishimo on Sunday May 23, 2021 @08:31AM (#27254555)
Is it actually slower though? I feel like that’s Vue’s entire marketing strategy. “We’re just as fast and small as React but include way more out of the box and it’s easier to grok for new people”.
Re:useStateMachine: A ½ kb state machine hook for React by jakelazaroff on Saturday May 22, 2021 @10:32AM (#27246876)
My experience is mixed but mostly positive.

- Agreed about useState (and useReducer). They’re simple and they get the job done.

- Agreed about useCallback as well, it’s a lot of boilerplate.

- State in general is a hard problem to deal with, but I’m not sure how hooks in particular encourage it? Class components had the same issue.

- IMO, useEffect is a huge footgun. I understand how it works, I understand how closures work, but it is by far the biggest source of hook-related bugs I’ve experienced.

- This eslint plug-in will solve your dependency list woes: https://www.npmjs.com/package/eslint-plugin-react-hooks

Re:useStateMachine: A ½ kb state machine hook for React by ketzo on Saturday May 22, 2021 @01:26PM (#27248545)
+1 for that eslint plugin, I was just idly wondering if something like that existed earlier this week. Thanks.
Re:useStateMachine: A ½ kb state machine hook for React by jakelazaroff on Saturday May 22, 2021 @03:07PM (#27249389)
Unless your app is peculiar in some way I’d recommend using something like Create React App, which includes it automatically. https://create-react-app.dev
Re:useStateMachine: A ½ kb state machine hook for React by mrighele on Saturday May 22, 2021 @09:23AM (#27246269)
> If you want something to execute once initially you can use useEffect with an empty dependency list, but note that then there’s no way of accessing updates values (in callbacks) and everything will reflect the initial state. Often you’ll have to use useRef just to keep track of the current state. Or maybe useState?

I'm not sure if I understood what you mean, but note that useState accepts not only the updated state, but also a function that takes the current state as argument and return the updated state.

In other words, instead of something like this

useEffect( async () => {

  ...

  const someValue = await someFunction();

  setState({...state, someValue });
}, [... ] );

you should use something like this

useEffect( async () => {

  ...

  const someValue = await someFunction();

  setState( currentState => ({...currentState, someValue }));
}, [ ... ] );

(the example is with async but it is the same for regular callbacks)

Re:useStateMachine: A ½ kb state machine hook for React by jakelazaroff on Saturday May 22, 2021 @10:19AM (#27246764)
Note that you shouldn’t (can’t?) actually pass an async function directly to useEffect, since it returns a promise: https://github.com/facebook/react/issues/14326
Re:useStateMachine: A ½ kb state machine hook for React by jacobedawson on Saturday May 22, 2021 @10:48AM (#27247033)
Not true, see Gaeron's direct reply in the thread you linked to, that's been the standard for 3 years and works like a charm - useEffect specifically is the hook for handling async functions ("impure effects").
Re:useStateMachine: A ½ kb state machine hook for React by azangru on Saturday May 22, 2021 @11:01AM (#27247168)
Notice the words "pass to useEffect" in the parent comment, and the code snippet in the grandparent they are commenting on. The type of the callback function that useEffect accepts is () => void rather than () => Promise<unknown>. What's not true about that?
Re:useStateMachine: A ½ kb state machine hook for React by jakelazaroff on Saturday May 22, 2021 @11:06AM (#27247214)
I reworded it to make it a bit more clear (at least, I thought so) — "pass an async function to useEffect", meaning the argument supplied to useEffect itself, rather than "use directly within" which is ambiguous. Re-added "directly" to hopefully make even more clear. Sorry for the confusion!
Re:useStateMachine: A ½ kb state machine hook for React by zebnyc on Saturday May 22, 2021 @02:30PM (#27249079)
I usually use an IIFE to encapsulate the async block inside the useEffect. Works like a charm!
Re:useStateMachine: A ½ kb state machine hook for React by tanaypingalkar on Saturday May 22, 2021 @04:32PM (#27250014)
True, you cannot do that in useEffect, it will throw you error. And probably your linter will tell you. You can't even use your own or third party hooks in side useEffect. This also throw error I don't know why?
Re:useStateMachine: A ½ kb state machine hook for React by gassiss on Saturday May 22, 2021 @11:45PM (#27252262)
Because you could be nesting hooks, which would bring all sorts of weird behavior.
Re:useStateMachine: A ½ kb state machine hook for React by mrighele on Saturday May 22, 2021 @01:24PM (#27248531)
you're right, good catch. Usually it's the TS compiler that prevents me doing that.
Re:useStateMachine: A ½ kb state machine hook for React by ricardobayes on Saturday May 22, 2021 @09:55AM (#27246565)
You can use a boolean ref for this in the useEffect to keep track whether it was the first render or not. https://reactjs.org/docs/hooks-faq.html#can-i-run-an-effect-...
Re:useStateMachine: A ½ kb state machine hook for React by phailhaus on Saturday May 22, 2021 @03:03PM (#27249342)
> Debugging is painful. You forget one value in your dependency list and the weirdest things happen

This should never happen. The only downside to hooks is that the eslint plugin is _required_, not optional. It is not worth the pain without it, but you'll be in a Whole New World once you do it. Since you can auto-fix every time, it'll become second nature and you'll never forget a dependency again. You can focus on getting your application to work.

Re:useStateMachine: A ½ kb state machine hook for React by simion314 on Saturday May 22, 2021 @11:05AM (#27247207)
>You forget one value in your dependency list and the weirdest things happen.

This is what I hate in angular1 , there are at least 3-4 ways you can mess up a simple data-binding and there is no error or warning to inform you that something is not right so you waste a lot of time to figure it out.

I used react a few years back but it seems that this days it got hyper complex.

Re:useStateMachine: A ½ kb state machine hook for React by bobthepanda on Saturday May 22, 2021 @12:32PM (#27248079)
As far as I can tell you can just not use hooks, if you (and the rest of your contributors) agree.
Re:useStateMachine: A ½ kb state machine hook for React by wayneftw on Saturday May 22, 2021 @09:15AM (#27246200)
> You forget one value in your dependency list and the weirdest things happen.

Don't you get eslint warnings right in your editor?

If you're using VS Code there's an extension for that...

Re:useStateMachine: A ½ kb state machine hook for React by Waterluvian on Saturday May 22, 2021 @12:55PM (#27248278)
Not only this but I need the freedom to control the dependency list for an effect. Sometimes it isn't as simple as "every variable being referenced inside the effect."
Re:useStateMachine: A ½ kb state machine hook for React by MispelledToyota on Saturday May 22, 2021 @09:56PM (#27251836)
that's a bit confusing. While you can sometimes get away with leaving out dependencies, and then you don't have to useMemo or useCallback as often, it seems like there is a much larger downside to having potentially stale values in your effect. Leaving them out to me would result in the potential for weird future bugs and race conditions.
Re:useStateMachine: A ½ kb state machine hook for React by aphextron on Saturday May 22, 2021 @08:19PM (#27251411)
>but note that then there’s no way of accessing updates values (in callbacks)

This is by design. When you start making a component worry about what it needs to do on an update, rather than just rendering its data, you are introducing a whole new level of complexity. That's why class based React components could turn into these unwieldy confusing things where you never knew for certain what was going to render every time, because the shouldComponentUpdate method gets stuffed full of business logic.

Re:useStateMachine: A ½ kb state machine hook for React by schwartzworld on Saturday May 22, 2021 @01:09PM (#27248381)
Regarding useCallback, you can probably skip it in most cases, unless the extra renders are a problem for you.

Linters should help with missing dependencies.

Re:useStateMachine: A ½ kb state machine hook for React by ng12 on Saturday May 22, 2021 @05:50PM (#27250587)
Yes! useCallback is an optimization and using it prematurely can be problematic.
Re:useStateMachine: A ½ kb state machine hook for React by joshribakoff on Saturday May 22, 2021 @06:25PM (#27250814)
You can use OOP or whatever you want to build your abstraction and then surface that as a hook, rather than using hooks as a way to do all your logic. This is similar to how there are npm packages that just import some other js package “foo”, wrap its api in a react component, and reexport it as react-foo

I’m curious what you think of https://rxstore.dev/ it basically is a pattern I tried to outline where you write logic with rxjs and it tries to bridge the gap to react/hooks for you. I address some of your points in the faq.

Re:useStateMachine: A ½ kb state machine hook for React by jimrandomh on Saturday May 22, 2021 @01:56PM (#27248816)
> You forget one value in your dependency list and the weirdest things happen.

There's an eslint plugin specifically for detecting this, which should probably be considered mandatory.

Re:useStateMachine: A ½ kb state machine hook for React by grandpoobah on Saturday May 22, 2021 @01:52PM (#27248774)
> You forget one value in your dependency list and the weirdest things happen

Really? I've been working with hooks for months, with code in production, and I hardly ever pass more than one or two items to the dependency list. The only time I really had any trouble with dependencies was when I was updating appContext inside a hook.

Re:useStateMachine: A ½ kb state machine hook for React by mikojan on Saturday May 22, 2021 @09:49AM (#27246504)
Seconded. Plus, you start writing wrapper functions for standard Javascript APIs (e. G. window.setInterval) to force them into Reacts data model.
Re:useStateMachine: A ½ kb state machine hook for React by erikpukinskis on Saturday May 22, 2021 @01:05PM (#27248349)
Why would you do that? What’s wrong with this?

    useEffect(() => {
      const interval = setInterval(myFunc, 1000)
      return () => clearInterval(myInterval)
    },[])
I think one of the keys to React is not to fear the boilerplate.

If you find yourself typing the same code too often, there’s probably a higher level abstraction that you should find, way above the level of setInterval.

I find coders often try to DRY up low level code to the detriment of actually dealing with their _application_ architecture.

In general, you should use the tools as provided, boilerplate and all, and then focus your real brain energies on the specific domain problems that only your application needs.

Creating thin wrappers on external tools to squeeze the last tiny bits of DRYness is not only usually a waste of time, but it makes your code unreadable. People know how setInterval and useEffect work. If I see useInterval I have to go read your code to know what’s happening. Especially if you made it configurable. And people _will_ tend to add configuration to these wrappers over time as needs change.

Re:useStateMachine: A ½ kb state machine hook for React by lunfard00 on Saturday May 22, 2021 @02:04PM (#27248871)
in my experience is better to have customs hooks like useTimeout (react-use library is awesome) so is easier to test. Mocking hooks feels nice, mocking the browser API not so much...
Re:useStateMachine: A ½ kb state machine hook for React by jameshart on Saturday May 22, 2021 @10:20AM (#27246779)
... which is a good idea anyway because you want your code to be testable.
[dead]
Re:useStateMachine: A ½ kb state machine hook for React by mikojan on Sunday May 23, 2021 @07:58AM (#27254395)
Why would you be down voting this? Parent's statement is completely nonsensical. If you wanted to test a function irrespective of window.setInterval's implementation you would just PASS window.setInterval as a parameter to that function. You would NOT add a wrapper function for window.setInterval because it is completely useless.
Re:useStateMachine: A ½ kb state machine hook for React by jameshart on Sunday May 23, 2021 @10:41AM (#27255299)
The function you’re talking about would be a react functional component. I don’t think passing window.setInterval in as a prop to a react component is a particularly common approach to achieving component testability - though by all means give it a try.

I don’t think it’s ‘nonsensical’ though to suggest that it’s a fairly common practice in testing to not want your unit tests to actually set up recurring callbacks.

Isolating an external side effect to make it testable, as well as to align its abstraction with the one that your framework uses is a common pattern anyway.

I’m not sure why this angers you so much?

Re:useStateMachine: A ½ kb state machine hook for React by k__ on Saturday May 22, 2021 @08:11AM (#27245745)
They fit so well into React it's crazy.

But they're also soooo idiosyncratic which makes them rather ugly on a general level.

Re:useStateMachine: A ½ kb state machine hook for React by codeflo on Saturday May 22, 2021 @08:23AM (#27245828)
They also come with many restrictions and rules on correct and efficient usage, not all of them checked by ESLint, that make the learning curve a bit brutal.

But yes, insanely useful once you get the hang of them, they enable forms of abstraction and composability that you'll sorely miss when working in other UI frameworks.

Re:useStateMachine: A ½ kb state machine hook for React by radicalbyte on Saturday May 22, 2021 @09:16AM (#27246203)
Aren't there proper TypeScript bindings which catch (more) cases?
Re:useStateMachine: A ½ kb state machine hook for React by jokethrowaway on Sunday May 23, 2021 @08:13AM (#27254479)
It's a good abstraction (definitely a massive improvement over the awkward classes) but it's built on so much react tech that you need limits which don't make sense (all the rules you need to remember) and when things break you're in for a world of pain.

You can definitely have "hooks" that are just normal js functions without limits.

My favourite public example of this is definitely solid.js (by ryansolid).

In general, I'm grateful to react / facebook for bringing in the spotlight the hyperscript way of doing applications and pushing tons of developers to develop similar libraries - but technically react is bloated and a ugly corporate mess.

Similar considerations for redux and elm.

Re:useStateMachine: A ½ kb state machine hook for React by kabes on Sunday May 23, 2021 @03:38AM (#27253114)
React hooks allows for reusable bits of logic. Reusable bits of logic are a great idea for a UI framework. But react hooks is a terrible implementation of that idea.

You're no longer writing plain javascript, you're writing in some terribly verbose language where everything from variable declarations to function expressions needs to be wrapped, making it hard to integrate with this party APIs and small details can have a big impact on performance.

Both vue 3 and svelte show it can be done better.

Re:useStateMachine: A ½ kb state machine hook for React by antjanus on Saturday May 22, 2021 @11:32AM (#27247480)
that's pretty much how I feel, too. I really love the flow of hooks and I write a ton of them -- majority of the logic I write tend to end up in hooks and I really love that.

There's something to having a function that can hold state or load its state on mount, etc.

Re:useStateMachine: A ½ kb state machine hook for React by an_opabinia on Saturday May 22, 2021 @08:18PM (#27251409)
Unsurprising it took people almost a decade to discover "depend()" from Meteor.