Recoil 0.1.1

Welcome to Recoil version 0.1.1! This release has performance improvements and introduces several experimental features such as support for React Native, working with Snapshots outside of React, and atom effects for managing side-effects of atoms such as logging, synchronization with external stores, persistence, etc.

Also, nightly builds are now available via the nightly branch.

Performance

Several changes to improve Recoil's performance:

  • Updates performed during useRecoilCallback() are now batched, which avoids copying data structures or performing updates for intermediate states. This allowed setting 5,000 atoms in a loop to go from 10s -> 25ms with some of our stress tests. (@davidmccabe)
  • Recoil also now avoids looking up selector values in cache if the selector's dependencies have not changed. This improved some applications with complex data-flow graphs by 30-40x. (@davidmccabe)

React Native (Experimental)

Recoil should now work with the React Native environment. However, similar to server side rendering, it is not officially supported. (#114 - @jacques-blom, @mondaychen)

Atom Effects (Experimental)

Effects for atoms simplifies managing side-effect policies for atoms on a per-atom basis as part of the atom() or atomFamily() definition. Effects can be used for interesting applications such as logging and state synchronization or persistence with external storage such as remote databases, local storage, browser URL history, etc. For example, you could use an atom as a local copy of some user state and provide an effect to subscribe to changes on a server to update the local copy and for local changes to write-through and update the server. (#680, #380, #381, #384, #385, #448, #449, #412, #591, #634, #682@drarmstr, @csantos4242)

Snapshots for Testing (Experimental)

Snapshots can now be constructed outside of a React context. This can be useful for testing or evaluating selectors outside of a React context. (#649@drarmstr, @habond)

Bug Fixes

Future Work

In a future release, Recoil will automatically free the memory used by atoms and selectors that are no longer used, and will perform better with larger numbers of atoms. (@davidmccabe)

Releasing our prototype Chrome developer tools. (@maxijb)

Libraries of effects for common state persistence, such as browser local storage or URL history. (@bezi)

Thanks for your continued interest in Recoil!

Recoil 0.0.11

Today we are releasing Recoil 0.0.11. It contains bug fixes, new features, better performance, and experimental compatibility with Concurrent Mode. Thank you so much to everyone who contributed to this release!

Recoil 0.0.10

Recoil 0.0.9 and 0.0.10 is being released with some bug fixes, TypeScript support, and a new API for Recoil Snapshots to observe, inspect, and manage global Recoil atom state. Thanks again to everyone who helped make this possible and stay tuned for more exciting developments coming soon!

Recoil 0.0.8 版本发布

今天我们发布了 Recoil 0.0.8 版本。它包含错误修复和新功能。非常感谢为此版本做出贡献的每个人!看到这么多人做出了贡献,真是太神奇了。

错误修复

  • 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.

新功能

对 TypeScript 的支持

TypeScript 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.

并发助手

We'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.

readOnlySelector

This simply wraps a read-write RecoilState in a read-only interface.

接下来的规划

我们正在努力改进观察(observation)和持久化(persistence)方面的 API,提高速度和内存管理以及对并发模式的支持。非常感谢您尝试使用 Recoil,我们希望您能继续用下去,一起期待未来的变化!