DEV Community

loading...
Cover image for RecoilJS in practical - complex application

RecoilJS in practical - complex application

Thanh Minh
Software Engineer who love making high-standard products. I build http://refiapp.io - A GUI tool to interact with FireStore, more soon! Follow my Twitter to know more
Updated on ・5 min read

Hi there,
I just use Recoil for my own product for the first time.

So I decided to share my own experience when using Recoil 🤘

Why?

With the non-requirement of Refi App, it must be fast to bring the best DX so I need something to manage the state in a very optimized way

Why not Redux? Zustan? DVA?

  • The boilderplace is so fukin hard. Besides, it really hard for optimizing to only render a component which subscribe to a sub-tree state. I need to use selector, memorize, immutable, ...

Why not MobX? MST?

  • It has been a long time since I last use Mobx, MST. It's cool, but now the world has changed a lot, no more Class component, so I don't know it supports a lot.
  • One more thing I don't want to use MobX is that the API is changed a lot in each major version. No! I don't want to use an outdated library for the rest of my life
  • I feel can not control how Component will render when I use MobX

Why Recoil?
Alt Text

  • It solves my concern, each component is subscribed to a very small state object (called atom) and only render once they changed
  • It plays nice with Functional Component. You can easily change useState to useRecoilState and vice versa. It's cool because "Alway use local state, only move it to global once needed"
  • I can map the product concept to state in my brain. A cell in a table should be an atom, so that the cell will render on its own.

How can I struct my state?

When using recoil, your state will build from pieces of atom - A bottom-up approach. So that if you don't have a strategy for structuring it, you will end up with tons of atom

Lots of atom

I decided to orders those atoms by

  • firebase atoms
  • navigator atoms
  • UI atoms
  • hotkeys atom

My atoms

If it is biz state, I divided it by domain
If it is for something to manage display, I divided it by its function

As you can see in the images, I also make a .action.ts files. Once using recoil in a complex app, you will often need to update state of many atoms for one action.
For eg: Once users click on the Commit button, I will need to submit all the modified/new/deleted documents to the server, I also need to update a UI atom to show loading.

By splitting all actions to .action.ts file. I can list out all the use cases and convenient to not mess my mind once add or edit something.

Alt Text

One more thing is all the atoms, selectors must postfix with Atom. If not your brain will get confused when using it. Is this object is Atom Value, Atom State, or just a local state?

For that strategy, RefiApp tech about 60 atoms object so far. I'm happy with the current status but I think I gonna divide it for smaller if the app is grow

The funny parts

Funny parts

  • As I write above, it really easy to convert from useRecoilState to useState which is free my brain a lot. I don't need to ask myself, should I put it at global every time I try to introduce a new state.
  • An atom state can easily convert to selector and vice versa. Why I will need that? Alt Text

In the image above, I have a propertyListAtom to store the propertys that will show in each collection table. It will have an empty array [] as the default value. But I have a case that if users access a collection for the first time, I will generate some property to put on that list so that I introduce a null type for that atom. If I change the type of propertyListAtom then I gonna need to find everywhere using that atom to make an update.
No, you don't need to do that!. I just add a new atom propertyListCoreAtom and turn my old atom one to selector. Really enjoy!

  • Components will only render if its subscribed atoms update which is my own goal. No more energy to put on a stupid thing like redux and selector...

The awful parts

awful parts

  • You have to write all the logic in a component, there is no official way to mutate a state from outside. I know they have reason to make it, but it feels poor for developers to follow it. But I found a way to eliminate that

    There is a way to update states on recoilJS outside of component? #289

    So I'm trying recoilJS for a js game that I am building and it pretty neat, but the need to update atoms from components only feels like a limitation.

    To create a game loop, I put all the logic on empty component so I will be able to read and write states. Even if I will construct the logic outside of the component, I will need especially move different stats around all the time. There is a way to update atoms outside of react component (not via hooks)?

  • There are some issues on performance still not solve yet. The components will render if the selector value is not changed (their dependencies changed)

    The component rerender even the value from selector is not change #924

    How to reproduce

    https://codesandbox.io/s/recoil-test-8jove?file=/src/App.js

    • I have an atom to keep track an array of item - AtomA
    • A selector to validate the length of above array - SelectorB

    So every time I add new item to AtomA but the SelectorB still return same result, the component subscribe to it always rerender

    </div>
    <div class="gh-btn-container"><a class="gh-btn" href="https://github.com/facebookexperimental/Recoil/issues/924">View on GitHub</a></div>
    
    Enter fullscreen mode Exit fullscreen mode



  • I have a collection contains for about 100 documents. And I tried to update 100 atoms once I received the document data, the app is hanged. The recoil and react is not smart enough to batch those update! But it turns on an idea in my head 💡 which this approach I can batch update my app which out to do lots thing and the result is incredible. I called this approach is Separated tree timeline, and it also applicable for Redux, let's do it on the next post Seprated tree timeline

  • You can not subscribe to an atom value without making your component rerender. I solve that by introducing RxJS to my code, not that hard when combining them

  • The only debug tool that worked for me is console. Despise there some DevTool for Recoil but it's buggy and the DX is bad

  • Takeaways

    • ⚡️ Recoil is fast and easy to use
    • 🆙 It will boost productivity by "Use useState and convert it to useRecoilState when needed"
    • 😤 You gonna need a strategy to struct your atoms because it will be lots more
    • ⚠️ It still lacks some support on the advantage cases, you will need help for other libs.

Discussion (4)

Collapse
ageekdev profile image
₳GEEK

Recoil is a joke!

Collapse
thanhlm profile image
Thanh Minh Author

Why do you think that?

Collapse
robvirtuoso profile image
robvirtuoso

Recoil is the best thing ever. It's not convoluted at all.

April Fools!

Collapse
thanhlm profile image
Thanh Minh Author

There is still many things for recoil to go mainstream. But I think the concept is good, but the community is not large enough