top | item 23181375

Recoil – A state management library for React

109 points| dar8919 | 5 years ago |recoiljs.org

85 comments

order

mariusandra|5 years ago

I'm someone who through sheer coincidence (the right projects at the right time) happened/lucked into developing a React state management solution (https://kea.js.org). I've probably sunk hundreds of hours into this project by now.

5 hours before this HN post I asked for comparisons with different site management libraries on Github here: https://github.com/keajs/kea/issues/106

React state management is indeed a mess, meaning there are so many options to choose from. Unfortunately, even for me, a library author, it's hard to evaluate all of them properly. It would take just too much time and you never know where the real problems in any framework lay before you get neck-deep in code. And then you're too far to switch to another framework anyway.

Someone should really map out this landscape in more depth than just an awesome list. I hope the issue linked above can spark some discussion.

In any case, I personally think Kea is a very good solution for React state management, yet obviously I'm biased. Shrug.

And, to keep it on the topic, Recoil seems very low level and I think you need to invent a lot of things yourself to get a full app out of it. Cool to see people trying stuff though :).

And it's from Facebook so who knows, just by proxy it might become the default "atom" and someone will build molecules out of them...

volkandkaya|5 years ago

Keajs has been amazing I upgraded from 0.28 to 2.0 yesterday and had 1 small issue, had to delete [actions.] from the reducers.

I use to use just Redux and it was such a pain.

I know you have added even more features in v2 that I will need to take advantage of.

If you need to add examples https://versoly.com/ is what I built on top of keajs.

Has about 8 logic stores that have 100s of actions, thunks, reducers and some interesting selectors.

pezo1919|5 years ago

Never made any OpenSource lib, but I always had that gut feeling you are talking about here:

"Unfortunately, even for me, a library author, it's hard to evaluate all of them properly. It would take just too much time and you never know where the real problems in any framework lay before you get neck-deep in code. And then you're too far to switch to another framework anyway."

Putting that aside, to me RxJS and especially Cycle.js are "1 abstraction level above" React & friends. (Cycle can be used via React.)

What do you think about these?

weeksie|5 years ago

I'm not seeing how this works with more complex state flows. Doesn't seem much better than useReducer.

Frankly, for state management I still haven't found anything that beats Redux on its own without thunks or sagas or any of that bullshit. This is despite doing my level best to see if useReducer on its own would be sufficient. It's not.

Thunks are unmaintainable. Sagas are put together with bailing twine and rely too much on generators for my taste. (The source code is smart but it's also wildly complex.) All of it is castles in the sky for no good reason. You don't need any of that anyway.

davidmccabe|5 years ago

Well, I know that on one tool we saw a 20x or so speedup compared to using Redux. This is because Redux is O(n) in that it has to ask each connected component whether it needs to re-render, whereas we can be O(1).

useReducer is equivalent to useState in that it works on a particular component and all of its descendants, rather than being orthogonal to the React tree.

I think if you can model something with pure functions, you should. That's the approach we try to take for asynchronous processes: just a pure function that you happen to evaluate on some other process. This obviates the need for things like sagas. So I agree with you there I guess.

If you post an example of what you don't think it could handle I will tell you how we would handle it.

vosper|5 years ago

> I still haven't found anything that beats Redux on its own without thunks or sagas

There was a period in the early days of Redux where MobX [0] (and, perhaps to a lesser extend, MobX State Tree [1]) was the main competitor to Redux that I used to hear about. They both seem to be actively developed, but I don't hear so much about them any more. Have you ever look at either of them?

BTW I am 100% with you on Sagas.

[0] MobX https://mobx.js.org/README.html#introduction [1] MobX State Tree: https://mobx-state-tree.js.org/intro/philosophy

MoSattler|5 years ago

Having worked many years on mid to large scale React apps, I must say: In most cases component state (or useSate) and context works just fine.

Why is everyone so eager to add third party state libraries from the getgo? In most projects, Redux doesn't add net value.

madisvain|5 years ago

For complex state flows we use Kea JS. https://kea.js.org/

The library has been around for a while and reduces a lot of boilerplate.

Is also used by some quite big names.

nohuhu|5 years ago

One viable alternative for thunks and sagas that I came up with is using async functions and explicitly getting/setting state: https://github.com/riptano/statium#viewcontroller

Still a long list of chores to improve API, tooling, etc but very performant and battle tested.

christophilus|5 years ago

Agreed. But Redux loop is nice. Kinda like reframe for JavaScript.

darepublic|5 years ago

Mind describing why you dislike thunks

josemaenzo|5 years ago

I'm happy that we are moving away from the redux-like standard. I've tried the API in a dumb example and it looks clean and easy. https://codesandbox.io/s/three-buttons-example-with-recoil-q...

Still don't like the extra naming that you have to think of for every atom/value. Or also the key: prop that you have to define for every atom. It seems redundant for me.

And also, as a bundle-phobia guy I am. I think 22kb as extra library is ok but it could be better.

Liking a lot Recoil as solution for the three-button problem. I still think that the patch pattern I use with dop is better. In terms of simplicity and extra KB. This is the same example https://codesandbox.io/s/react-dop-nhj0j?file=/store.js

But I guess I say that because I'm the creator of dop. So I'm so open to critics :)

flowerlad|5 years ago

What is it about React that state management is such a such a hassle? This is not the case in other frameworks.

Consider iOS for example. Just add fields in App and you're done: https://developer.apple.com/documentation/swift/maintaining_...

Similarly in ASP.NET: https://docs.microsoft.com/en-us/previous-versions/aspnet/75...

Same in JSP: https://javabeginnerstutorial.com/jsp-tutorial/state-managem...

But in React it is such a huge issue, and there are multiple competing solutions. There must be something wrong with the design of React that is causing this.

speajus|5 years ago

Its a huge issue in all of those also. It just presents itself differently. JSP -- every click has to post or query param change re-renders the page. This gets hugely cumbersum with tree stateor anything other than basic switches. In a lot of ways its the one way data flow we all want in react. For a lot of pages its easy. Same with React, However complex state is so difficult to do in JSP you really can't write the apps we write today.

I would say React's state management is its great success, rather than its `functionalness` or its reactivity. No other UI framework (QT|WinForms|MOTIF|GTK) really ever handled state well.

gregkerzhner|5 years ago

Don't have experience with ASP or JSP, but managing state in React is vastly superior than iOS. Having a defined place to keep your data, and your view automatically refresh when it changes is the gold standard in user interface design. iOS does not easily have this kind of functionality, forcing people to use all sorts of messy techniques that are hard to follow and maintain.

The main "Apple approved" tools for user interface and state management are CoreData and UIKit. Both are imperative, mutable, and overall difficult to work with. This might be subjective, but I always notice just how poorly Apple's own apps work. There is always some button that is stuck in the wrong state, some feature that doesn't do what its supposed to, and some broken animation when views reload (I'm looking at you Podcast app). I can't know why, but my hunch is that Apple engineers are forced to use unwieldy patterns and technologies like CoreData, MVC, and UIKit, and are drowning in a sea of unmaintainable code.

As a response to the inadequate tools Apple provides, big industry leaders have stepped up and rolled their own declarative solutions. IGListKit from Instagram is a prime example of a declarative user interface solution thats vastly superior to Apple's. Going even further, Facebook basically ported React into iOS with ComponentKit.

It took Apple a good decade, but they are finally giving us these types of tools as well with SwiftUI. However, judging from its low adoption, so far they have not managed to fully get things right.

concerned_user|5 years ago

React is not a complete framework more of a templating engine and nothing more, it allows you to use any state management you want. It also makes it easy to add to existing projects without requiring rewrite of everything from the ground up.

simongray|5 years ago

> What is it about React that state management is such a such a hassle?

I'm not sure it's a hassle, just different schools of thought.

> This is not the case in other frameworks.

None of the examples you mention are reactive AFAIK. The point of React is that the UI is a function of the state. How exactly that is accomplished is where those different schools of thought come into the picture.

ng12|5 years ago

React has fantastic tools for state management built-in. The difficulty is a particular flavor of state management: data that lives in the "global" scope but can be used locally in components in a reactive fashion. We have some good tools for doing this but they all have drawbacks, hence the experimentation.

FWIW I've never seen a really great solution for this in any JavaScript framework. I read it as a sign of React's maturity that this is a focus.

nikivi|5 years ago

Perhaps it's due to React's architecture of one way data flow?

cwackerfuss|5 years ago

Check out easy-peasy. Ive used plain ol redux, mobx, and xstate, but easy-peasy is the fricken best. It's basically a redux wrapper that combines redux, thunks, reselect, redux logger, immer, and more into a super intuitive interface. The typescript support is super good and interacting with the API feels very modern and hook-driven.

https://github.com/ctrlplusb/easy-peasy

nwienert|5 years ago

If you want even cooler try overmind:

https://overmindjs.org

But Recoil is slightly different, designed to be “component first” essentially. Not global. It’s how my own personal mobx based library works. But this one likely has concurrent mode baked in.

knubie|5 years ago

Sounds a lot like re-frame[1] (which I believe predates Redux), they even call the state "atoms."

[1] https://github.com/Day8/re-frame

davidmccabe|5 years ago

The term 'atom' is a clojure-ism, that's where both I and reframe get it from.

jwiley|5 years ago

It would be useful to have a more direct comparison between this and Redux (assuming its not on the website and I missed it). In what use-cases is it preferable, in which would it not be a good fit? In the comments you mention O(1) vs O(n), diving more deeply into that would be helpful as well.

portlander12345|5 years ago

I’m working on a detailed comparison for the docs. Thanks for the feedback!

bfrydl|5 years ago

Seems like compared to Redux this would make server-side rendering very challenging. Each atom is a global singleton so I'm not sure how you could render individual requests.

davidmccabe|5 years ago

It’s actually designed to make server rendering easy. We’ll add a guide about this eventually. Atoms aren't global singletons: their values are scoped to React trees.

sheerun|5 years ago

In a year people will rediscover MobX I guess...

lai|5 years ago

Lol, MobX literally uses the concept of atoms under the hood.

mmerickel|5 years ago

Is there any support for changing multiple atoms at once / batch? This is where reducers shine to me - dispatching a single action from the ui in redux that multiple reducers can listen to and use to update their state.

Also is there any support for getting the values of atoms outside of a hook? For example from an async action that is not coupled to the render loop which also wants to know the current value.

davidmccabe|5 years ago

If you update multiple atoms within a React batch, they will be updated at the same time, just as with React local state. You don't need to wrap the changes in anything to have them occur together.

In other words, this updates both of the atoms together:

  const [a, setA] = useRecoilState(atomA);
  const [b, setB] = useRecoilState(atomB);
  ...
  onClick={() => {
    setA(a => a + 1);
    setB(b => b + 1);
  }}

If the new values of multiple atoms are interdependent on each others' current values, it's possible to update multiple atoms together using the transactional/updater/function form, but we need to add a nicer interface for doing this. Coming soon! The nicer interface would probably look something like this:

  const update = useTransactionalUpdate([atomA, atomB]);
  ...
  onClick={() => {
    update(([a, b]) => [a + b, b - a]);
  }}
It's then easy to make a hook that provides a reducer-style interface over a set of atoms. But now, unlike with Redux or useReducer, each atom still has its own individual subscriptions!

rhacker|5 years ago

Seems to be roughly the same amount of boilerplate as useContext, so I don't fully understand the separate purpose for it?

tshaddox|5 years ago

Recoil allows you to create atoms and selectors in loops without having to add an entire new Context.Provider component to the root of the React component tree, which would obviously not be viable since the entire tree would need to be torn down each time.

bodhibyte|5 years ago

Can anyone shed some light on if and how this might be used together with xstate (https://xstate.js.org/) which is based on the SCXML spec?

ecnrvsrp|5 years ago

Anyone else see Svelte stores when they look at this?

sawyerjhood|5 years ago

Great work on this davidmccabe! I remember hearing about this just before I left FB and am so glad that it is open source now.

rsify|5 years ago

I wish he would have shown the heavy tree example in 11:55 without the library, seems cute and all but if you don't provide a comparison it's hard to take seriously.

saranshk|5 years ago

Conceptually, this looks very similar to observables and RxJs. Should be interesting to explore further.

pppm|5 years ago

Ffff