Store

The API was created to satisfy the need of an external state store which does not reside within the application tree, and allows for precision updates when state changes.

Creating a Store

To create a store, you need to provide two arguments to the function:

  1. Initial State: The initial state of your store.
  2. : This is a function that receives two arguments - setState and getState - and returns an object containing methods for interacting with the store state. These methods will be accessible through the returned store object.
import { createStore } from "kaioken"

const useCountStore = createStore(0, (set, get) => ({
  increment: () => set((state) => state + 1),
  decrement: () => set((state) => state - 1),
  add: (value) => set(() => get() + value),
}))

Accessing Store State and Methods

There are two main ways to interact with the store:

  1. useStore hook: A Store object is callable within a component and returns the current store value and methods.
    function Counter() {
      const { value, increment, decrement } = useCountStore()
    
      return (
        <div>
          <p>Count: {value}</p>
          <button onclick={increment}>Increment</button>
          <button onclick={decrement}>Decrement</button>
        </div>
      )
    }
    
    • You can provide a function to useStore to return a computed value. This will cause the component to only update when the result of that computation changes:
      function TodoItem({ id }) {
        const { value: todo, toggle } = useTodoStore((state) => {
          return state.find(item => item.id === id)
        })
        // ...
      }
      
    • You can also provide a second function, allowing you to specify how the result of your computation should be compared:
      function TodoList() {
        const { value: items } = useTodoStore(null, (prev, next) => {
          return prev.length === next.length
        })
      
        return (
          <ul>
            {items.map((item) => (
              <TodoItem key={item.id} id={item.id} />
            ))}
          </ul>
        )
      }
      
      In the above example, the TodoList component will only update when the number of items in the store changes. We can also provide null as the first argument, which means the comparison will use the current state.
  2. Direct Access: You can also access the store's methods and state directly using the returned object from createStore:
    useCountStore.getState() // Returns the current state
    useCountStore.setState((state) => state + 1) // Updates the state
    useCountStore.methods.increment() // Calls the method defined in the method factory
    
    /**
     * Subscribe to the store, providing a function to run whenever state changes. 
     * Subscribing in this way returns a function to unsubscribe.
     */
    const unsub = useCountStore.subscribe((newValue) => console.log(newValue))