1.1.6 • Published 10 months ago

@fransekman/store v1.1.6

Weekly downloads
-
License
MIT
Repository
github
Last release
10 months ago

@fransekman/store

A tiny state management library for React.

Getting started

  1. Install the package:
npm i @fransekman/store
  1. Create a store:
// todoStore.ts
import { createStore, useStore } from "@fransekman/store";

type Todo = {
    text: string;
    completed: boolean;
};

interface TodoState {
    input: string;
    todos: Todo[];
}

const initialState: TodoState = {
    input: "",
    todos: [],
};

const todoStore = createStore(initialState, (set) => ({
    setInput: (input: string) => set({ input }),
    addTodo: (text: string) =>
        set((state) => {
            const newTodos = [...state.todos, { text, completed: false }];
            return {
                todos: newTodos,
                input: "",
            };
        }),
    toggleTodo: (index: number) =>
        set((state) => {
            const newTodos = [...state.todos];
            newTodos[index].completed = !newTodos[index].completed;
            return {
                todos: newTodos,
            };
        }),
}));

export const useTodoStore = () => useStore(todoStore);
  1. Use the store:
// Todos.tsx
import { useTodoStore } from "./todoStore";

export const Todos = () => {
    const { state, actions } = useTodoStore();

    return (
        <div>
            <h1>Todos</h1>
            <input
                type="text"
                value={state.input}
                onChange={(e) => actions.setInput(e.target.value)}
            />
            <button onClick={() => actions.addTodo(state.input)}>Add</button>
            <ul>
                {state.todos.map((todo, index) => (
                    <li>
                        <input
                            type="checkbox"
                            checked={todo.completed}
                            onChange={() => actions.toggleTodo(index)}
                        />
                        <span>{todo.text}</span>
                    </li>
                ))}
            </ul>
        </div>
    );
};

Example usage with React Context

Useful when you need to initialize the state using component props.

// todoStore.ts
import { createStore, useStore } from "@fransekman/store";
import { createContext, useContext } from "react";

type Todo = {
    text: string;
    completed: boolean;
};

export interface TodoState {
    input: string;
    todos: Todo[];
}

export const createTodoStore = (initialState: TodoState) => {
    return createStore(initialState, (set) => ({
        setInput: (input: string) => set({ input }),
        addTodo: (text: string) =>
            set((state) => {
                const newTodos = [...state.todos, { text, completed: false }];
                return {
                    todos: newTodos,
                    input: "",
                };
            }),
        toggleTodo: (index: number) =>
            set((state) => {
                const newTodos = [...state.todos];
                newTodos[index].completed = !newTodos[index].completed;
                return {
                    todos: newTodos,
                };
            }),
    }));
};

export const TodoStoreContext = createContext<ReturnType<
    typeof createTodoStore
> | null>(null);

export const useTodoStore = () => {
    const store = useContext(TodoStoreContext);
    if (!store) {
        throw new Error("useTodoStore must be used within a TodoStoreContext");
    }
    return useStore(store);
};
// TodoStoreProvider.tsx
import { FC, ReactNode, useMemo } from "react";
import { createTodoStore, TodoState, TodoStoreContext } from "./todoStore";

export const TodoStoreProvider: FC<{
    initialState: TodoState;
    children: ReactNode;
}> = ({ initialState, children }) => {
    const store = useMemo(() => createTodoStore(initialState), [initialState]);
    return (
        <TodoStoreContext.Provider value={store}>
            {children}
        </TodoStoreContext.Provider>
    );
};

Actions are optional

// Count.tsx
import { createStore, useStore } from "@fransekman/store";
import React from "react";

export const countStore = createStore({ count: 0 });

export const Count = () => {
    const { state, set, reset } = useStore(countStore);
    return (
        <div>
            <div>Count: {state.count}</div>
            <button
                onClick={() => set((state) => ({ count: state.count + 1 }))}
            >
                +
            </button>
            <button
                onClick={() => set((state) => ({ count: state.count - 1 }))}
            >
                -
            </button>
            <button onClick={reset}>Reset</button>
        </div>
    );
};
1.1.6

10 months ago

1.1.5

10 months ago

1.1.4

11 months ago

1.1.3

11 months ago

1.1.2

11 months ago

1.1.1

11 months ago

1.1.0

11 months ago

1.0.2

11 months ago

1.0.1

11 months ago

1.0.0

11 months ago