const valueAtom = createAtom("Initial Value");const todosAtom = createAtom([]);const useAddTodo = createSynergy(valueAtom, todosAtom).createAction(() => (value, todos) => {todos.current.push(value.current);value.current = "";});
const useTickTodo = createSynergy(todosAtom, tickedTodosAtom).createAction(index => (todos, tickedTodos) => {tickedTodos.current.push(todos[index]);});const useTickedTodos = createSynergy(todosAtom, tickedTodosAtom).createSelector((todos, tickedTodos) =>todos.filter(todo => tickedTodos.includes(todo)));const useAllTodos = todosAtom.useValue;
<SynergyProvider atoms={[todosAtom]}><SynergyProvider atoms={[tickedTodosAtom, starredTodosAtom]}><TodoList /></SynergyProvider><SynergyProvider atoms={[valueAtom]}>{/* Can access both valueAtom and todosAtom */}<TodoInput /></SynergyProvider></SynergyProvider>
<SynergyProvider atoms={[authAtom, userDataAtom]}><SynergyProvider atoms={[selectedItemAtom, isExpandedAtom]}><Menu name="File" /></SynergyProvider><SynergyProvider atoms={[selectedItemAtom, isExpandedAtom]}><Menu name="Edit" /></SynergyProvider></SynergyProvider>
You can synergyze atoms even if they are supplied by different providers, as long as they are in one path in the component hierarchy. Define localized state in a reusable component and have it interact with more globalized state further up in the hierarchy.
const useDropItem = createSynergy(selectedItemAtom, targetAtom) .createAction(() => async (selectedItem, target) => { // target atom was updated and will rerender // selectedItemAtom was only read from and will not target.current = selectedItem.current; } );
const useFetchData =createSynergy(dataAtom, isLoadingAtom).createAction(() => async (data, isLoading) => {isLoading.current = true;// Trigger rerenders of all components// reading from `isLoadingAtom`.isLoading = isLoading.trigger();const res = await fetch(url);data.current = await res.json();isLoading.current = false;});
Local State.
You can provide your state atoms high up in your component hierarchy to provide global state data such as user information or authentication data. Or you can inject atoms in a provider within small reusable components to provide contextual state within a small localized component hierarchy.
But most importantly, you can do both! Provide authentication data in a global synergy provider, and a list state in a localized provider within your list component for list items to consume. You can have many lists, each sharing the same atoms, but with their unique list state supplied by their respective provider. Also, you can define synergies that access both the localized list state and global authentication state.
synergies uses immer for immutable data structures. Apart from that, only 3kB of gzipped code is added by using synergies.
Complete typesafety is provided by Typescript declarations.
Use the well-known concept of middlewares to track errors, log state changes or debug issues.