Recoil 0.0.8
Today we are releasing Recoil 0.0.8. It contains bug fixes and new features. Thanks so much to everyone who contributed to this release! It's been amazing to see so many people contribute.
#
Bug Fixes- Fixed a bug where atoms that stored self-referential structures would cause an infinite loop. (@n3tr in #153)
- Fixed bugs affecting Server-Side Rendering. (@sbaudray in #53)
- Fixed build system and repository syncing problems. Many people contributed to this, especially @mondaychen and including @claudiopro, @dustinsoftware, @jacques-blom, @jaredpalmer, @kentcdodds, @leushkin, and @tony-go. It remains to get Jest and Flow to behave the same between internal and OSS.
#
Features#
TypeScript supportTypeScript definitions are now available via the DefinitelyTyped
repository.
atomFamily
and selectorFamily
#
These utilities help you create collections of related atoms or selectors, one for each value of some parameter. Instaed of manually creating a memoized function that returns an atom or selector, you can use atomFamily
and selectorFamily
. In the future, these utilities will also help with memory management.
The atomFamily
function returns a function from some parameter to an atom, creating a new atom for each value of the parameter that is passed in. For example, suppose you wanted to store a set of coordinates {x: number, y: number}
for every member of a collection identified by some ID
. Then you could write:
const coordinatesForID = atomFamily<{x: number, y: number}, ID>({ key: 'coordinatesForID', default: {x: 0, y: 0},});
and then access that state as follows:
function MyComponent({id}) { const [coordinates, setCoordinates] = useRecoilState( coordinatesForID(id) ); ...}
Each ID
passed to coordinatesForID
will get its own independent atom containing the coordinates. Each of these atoms has its own subscriptions, so a component that uses the state for a single ID will only be subscribed to changes to that one ID.
Similarly, selectorFamily
lets you create a different selector for each value of some parameter. For example, suppose you wanted to take each of those coordinates and rotate them by 180 degrees:
const rotatedCoordinatesForID = selectorFamily<{x: number, y: number}, ID>({ key: 'rotatedCoordinatesForID', get: id => ({get}) => { const coordinates = get(coordinatesForID(id)); return { x: -coordinates.x, y: -coordinates.y, }; }});
Note that the get
property of a selector family is a function that takes the parameter (in this case ID) and returns a function with a signature identical to the get
property of a single selector. In general, this is how all of the options for atom families and selector families work.
#
Concurrency helpersWe've introduced selector families for controlling concurrency in async selectors:
waitForAll
: requests all dependencies in parallel and waits for all of them to become available.waitForAny
: requests all dependencies in parallel and waits for any one of them to become available.waitForNone
: requests all dependencies in parallel but doesn't wait for any of them.noWait
requests a single dependency but doesn't wait for it to become available.
These can be used to retireve multiple dependencies in parallel and to write logic conditional on the status of an upstream dependency. For example, you can write a selector that conditionally provides a default value while an async process is in flight instead of propagating that loading state down to components.
constSelector
and errorSelector
#
These selector families simply return a constant value or always throw a given error, respectively.
#
readOnlySelectorThis simply wraps a read-write RecoilState
in a read-only interface.
#
What's NextWe're working on improvements to the observation and persistence APIs, improved speed and memory management, and support for Concurrent Mode. Thanks so much for trying Recoil, we hope you'll stick around and see what it becomes!