facebookexperimental / Recoil

Recoil is an experimental state management library for React apps. It provides several capabilities that are difficult to achieve with React alone, while being compatible with the newest features of React.
https://recoiljs.org/
MIT License
19.59k stars 1.18k forks source link

Calmm-js #21

Closed akheron closed 4 years ago

akheron commented 4 years ago

Please, have a look at calmm-js: https://github.com/calmm-js/documentation/blob/master/introduction-to-calmm.md

In a nutshell, it uses atoms like Recoil, but it lets you decompose the state with optics instead of hand-written selectors. Optics are super nice, because they also work in the write direction. They eliminate the need of writing glue code for selecting stuff from the atom or writing stuff in specific form to the atom. Decomposing an atom with an optic yields a new atom that updates each time the parent atom updates. When written to, the atom writes the new value back to the correct part of the parent atom. In essence, optics let you create read-write views on the state contained in the parent atom. There's no limit on the nesting, so you can decompose an atom with optics, even though it's already a decomposed atom itself.

Furthermore, calmm-js does subscribing to the atoms "one level deeper", at the DOM element level. Whenever a div, a, etc. DOM element is created with React.createElement, it checks whether props or children contains atoms. If they do, it subscribes to those atoms and only the element that renders the atom's value to DOM is re-rendered on updates. I think this is a huge point. If you subscribe to the atoms with a hook in the component you wrote, like Recoil does, the whole component (and all its children) will update when the atom updates. With calmm-js, only the actual DOM elements that depend on the value of the atom will update. (Calmm-js achieves this by requiring you to import React from a custom library that provides a slightly modified React.createElement)

@polytypic (the author of calmm-js) has published lots and lots of examples on CodeSandbox, see https://codesandbox.io/u/polytypic/sandboxes.


Calmm-js uses the partial.lenses library for optics. It's a very comprehensive optics library for JavaScript, but there's a downside: TypeScript's type system isn't flexible enough to allow adding typings for it.

I've recently published optics-ts, which is a fully typed optics library for TypeScript. I've also played with a typed atom implementation and a proof of concept for replicating the calmm-js architecture in a typed way. Here's a small demo: https://codesandbox.io/s/goofy-sun-j1zoz?file=/src/App.tsx

davidmccabe commented 4 years ago

Neat!

vjeux commented 4 years ago

Fwiw, Animated works the same way as Calm, where it provides an Animated.div that reads if props are animated values and just re-renders the component if that’s the case.

It also goes one level deeper and sends the description of the animation to the main thread/animation process so that it can run smoothly even though the js thread may be busy. (See useNativeDriver: true)

https://reactnative.dev/docs/animations