Hacker News new | ask | show | jobs
by knuthsat 2017 days ago
I think hooks and effects are really good. You can test them separately. You can write global reactions to state changes very easily.

I find hooks/effects better than mobx or redux. hooks/effects, redux, mobx would be my preference order. Although redux works so well that it can be used with hooks/effects.

For global state I would just use a React.Context with it's own effects. Most components do not have any async effects.

I do admit that when jumping into a new codebase with hooks/effects I often find people have just butchered the concept. But I find that when I jump into codebases with mobx and redux too. The butchering that people do with mobx is much worse, with massive module importing of global stores, misuse of `name?: type` inside stores because they want to initialize the store at a later time.

2 comments

IMO the new context and hook are the best thing that react has done. Hats off to whoever designed them.
Yep. I've watched the video that @BreakfastB0b referenced and must say I do not see how this can't be done with new hooks/effects.

I can easily have all the user settings accessed inside a small effect and react to events or not depending on the settings and it's composable and reusable.

Testing with jest/enzyme is still the same. I'm writing selectors, simulating clicks and the component rerenders. Mocking the effects or functions that effects use is also simple. With jest 26 and modern fake timers it's easy to test async effects and changes of state too.

I guess the only flaw of hooks/effects is that they not efficient because of so many effects fetching the same state but they are efficient enough. For example, mobx would be extremely efficient in that regard (any store.value access is just that, not a useState call with new () => {} instantiated on every rerender.

  You can write global reactions to state changes very easily.
This is exactly the problem, shared mutable state leads to "spooky action at a distance". It results in causal connections between parts of your codebase that are not reflected in the control flow of your code. If you have immutable unidirectional data flow causal relationships between parts of your code base must be reified in the control flow of the language.

  Most components do not have any async effects.
At least when using Apollo / GraphQL almost every component ends up with async effects.

I think this talk by Andre Staltz is the best explanation and solution of the problem https://www.youtube.com/watch?v=SXdtrhn8iII

But the state is not mutable, the state is inside a React.Context that provides functions that manipulate it. It's practically the same as redux. You still need to have async actions with redux and use these actions.

mobx on the other hand is exactly that, the state is globally mutable, anyone can import it from anywhere to anywhere.