Returns a function that returns a writeable
key- A unique string used to identify the atom internally. This string should be unique with respect to other atoms and selectors in the entire application.
default- The initial value of the atom. It may either be a value directly, a
Promisethat represents the default value, or a function to get the default value. The callback function is passed a copy of the parameter used when the
atomFamilyfunction is called.
atom represents a piece of state with Recoil. An atom is created and registered per
<RecoilRoot> by your app. But, what if your state isn’t global? What if your state is associated with a particular instance of a control, or with a particular element? For example, maybe your app is a UI prototyping tool where the user can dynamically add elements and each element has state, such as its position. Ideally, each element would get its own atom of state. You could implement this yourself via a memoization pattern. But, Recoil provides this pattern for you with the
atomFamily utility. An Atom Family represents a collection of atoms. When you call
atomFamily it will return a function which provides the
RecoilState atom based on the parameters you pass in.
atomFamily essentially provides a map from the parameter to a atom. You only need to provide a single key for the
atomFamily and it will generate a unique key for each underlying atom. These atom keys can be used for persistence, and so must be stable across application executions. The parameters may also be generated at different callsites and we want equivalent parameters to use the same underlying atom. Therefore, value-equality is used instead of reference-equality for
atomFamily parameters. This imposes restrictions on the types which can be used for the parameter.
atomFamily accepts primitive types, or arrays or objects which can contain arrays, objects, or primitive types.
atomFamily() takes almost the same options as a simple
atom(). However, the default value can also be parameterized. That means you could provide a function which takes the parameter value and returns the actual default value. For example:
selectorFamily instead of
selector, you can also access the parameter value in a
default selector as well.
One advantage of using this pattern for separate atoms for each element over trying to store a single atom with a map of state for all elements is that they all maintain their own individual subscriptions. So, updating the value for one element will only cause React components that have subscribed to just that atom to update.
Persistence observers will persist the state for each parameter value as a distinct atom with a unique key based on serialization of the parameter value used. Therefore, it is important to only use parameters which are primitives or simple compound objects containing primitives. Custom classes or functions are not allowed.
It is allowed to “upgrade” a simple
atom to be an
atomFamily in a newer version of your app based on the same key. If you do this, then any persisted values with the old simple key can still be read and all parameter values of the new
atomFamily will default to the persisted state of the simple atom. If you change the format of the parameter in an
atomFamily, however, it will not automatically read the previous values that were persisted before the change. However, you can add logic in a default selector or validator to lookup values based on previous parameter formats. We hope to help automate this pattern in the future.