selector()

The selector methods allow you to create reusable selectors that can compute derived state with optional parameters. Selectors are required when creating a store, even if empty.

import { createStore } from 'finalstore';
 
const store = createStore({
  states: {
    todos: [] as { id: number; text: string; completed: boolean }[]
  },
  actions: {}, // Required, even if empty
  selectors: {
    // Selector with parameter
    filteredTodos: (state, completed?: boolean) => {
      if (completed === undefined) return state.todos;
      return state.todos.filter((todo) => todo.completed === completed);
    },
    // Selector without parameter
    totalTodos: (state) => state.todos.length
  }
});

Inside Components (useSelector)

Use the useSelector for reactive state in components:

function TodoList({ showCompleted }: { showCompleted: boolean }) {
  // Use useSelector for reactive updates
  const todos = store.useSelector.filteredTodos(showCompleted);
 
  return (
    <ul>
      {todos.map((todo) => (
        <li key={todo.id}>{todo.text}</li>
      ))}
    </ul>
  );
}
 
function TodoStats() {
  // Both will trigger re-renders when their values change
  const completedTodos = store.useSelector.filteredTodos(true);
  const total = store.useSelector.totalTodos();
 
  return (
    <div>
      <p>Total: {total}</p>
      <p>Completed: {completedTodos.length}</p>
    </div>
  );
}

Outside Components (getSelector)

Use the getSelector for non-reactive state access:

function handleTodoAction() {
  // Get current values synchronously
  const completedTodos = store.getSelector.filteredTodos(true);
  const total = store.getSelector.totalTodos();
 
  console.log(`${completedTodos.length} of ${total} todos completed`);
}
 
// Can be used in async functions
async function processTodos() {
  const todos = store.getSelector.filteredTodos(true);
  await saveTodos(todos);
}

Type Safety

Selectors are fully type-safe. TypeScript will ensure that:

  • The selector exists in your store's selectors
  • The parameter type matches the selector's expected parameter type
  • The return type matches the selector's defined return type
// TypeScript will catch these errors:
store.useSelector.nonexistentSelector(); // Error: Property doesn't exist
store.getSelector.filteredTodos(123); // Error: Expected boolean | undefined

On this page