Selectors
Selectors provide a way to create derived states. They can be created with the same atom
| create
function. There is one difference: selectors should have a get
method that will run whenever any of the states they are subscribed to changes.
Advantages
- Selectors are re-rendered only when any of the atom's they are subscribed to updates their state.
- They can return promises
import { create } from 'atomic-state'
const todos = create({
key: 'todos',
default: []
})
const completedTodosState = create({
key: 'completedTodos',
get({ get }) {
// This selector will re-render only when 'todos' changes.
// You can check that by adding a console.log :)
const todosState = get(todos)
return todosState.filter((todo) => todo.completed)
}
})
const useCompletedTodos = completedTodosState.useValue
function CompletedTodos() {
// Type is inferred here
const completedTodos = useCompletedTodos()
return <p>Completed todos: {completedTodos.length}</p>
}
Because selectors depend on other atoms' states, their state cannot be set
manually. This also means that actions
don't work inside them
They can also return promises:
import { create } from 'atomic-state'
const text = create({
key: 'text',
default: ''
})
export const searchResults = create({
key: 'searchResults',
default: [],
async get({ get }) {
const textState = get(text)
return fetch('/search?q=' + textState).then((res) => res.json())
}
})
export const useSearchResults = searchResults.useValue
Note that in this case the result of the selector is a Promise
, so it will
not be available while it's resolving. In that case, default
is required.
The return type will be inferred from it as well.
They can also subscribe to other selectors:
import { create } from 'atomic-state'
import { searchResults } from '@/states'
const infoState = atom({
key: 'info',
default: {
name: '',
searchResults: []
},
async get({ get }) {
const searchResultsValue = await get(searchResults)
return {
name: '',
searchResults
}
}
})
In this example, we are using async/await
because the current state of
searchResultsState
could still be a Promise