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