Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calmm-js #21

Closed
akheron opened this issue May 15, 2020 · 2 comments
Closed

Calmm-js #21

akheron opened this issue May 15, 2020 · 2 comments

Comments

@akheron
Copy link

akheron commented May 15, 2020

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
Copy link
Contributor

Neat!

@vjeux
Copy link
Contributor

vjeux commented May 16, 2020

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants