sveltedux Svelte Themes

Sveltedux

A full-featured Redux-like state management solution for Svelte 5 with runes support. This library provides a familiar Redux API while leveraging Svelte 5's reactivity system for optimal performance.

Redux-Esque State Management Library for Svelte 5

A full-featured Redux-like state management solution for Svelte 5 with runes support. This library provides a familiar Redux API while leveraging Svelte 5's reactivity system for optimal performance.

📚 Documentation

The complete documentation has been reorganized into separate files for better navigation and maintainability. Please refer to the documentation in the docs/ folder:

🚀 Getting Started

📖 Guides

🛠️ Best Practices

✨ Features

  • Redux-like API: Familiar patterns for developers coming from Redux
  • Svelte 5 Runes Integration: Built specifically for Svelte 5's reactivity system
  • TypeScript Support: Full TypeScript support with comprehensive type definitions
  • Async Actions: Built-in support for async operations with createAsyncThunk
  • API Data Fetching: Simple { data, loading, error } pattern for API calls
  • Middleware: Middleware support for logging, thunk, and custom middleware
  • Selectors: Memoized selectors for efficient state derivation
  • DevTools: Logger middleware for action logging
  • Utilities: Immutability helpers, action creators, and more
  • State Persistence: Built-in localStorage/sessionStorage integration

📦 Installation

npm install sveltedux

🚀 Quick Start

1. Define your store

// store.ts
import {
  createSvelteStore,
  combineReducers,
  createSlice,
  applyMiddleware,
  thunkMiddleware,
} from "sveltedux";
import { createAsyncThunk } from "sveltedux/async";

// Define your state types
interface User {
  id: number;
  name: string;
  email: string;
}

interface Todo {
  id: number;
  text: string;
  completed: boolean;
}

interface AppState {
  user: User | null;
  todos: Todo[];
  loading: boolean;
}

// Create async actions
const fetchUser = createAsyncThunk<User, number>(
  "user/fetchUser",
  async (userId) => {
    const response = await fetch(`/api/users/${userId}`);
    return response.json();
  }
);

// Create slices
const userSlice = createSlice({
  name: "user",
  initialState: null as User | null,
  reducers: {
    clearUser: () => null,
  },
  extraReducers: (builder) => {
    builder.addCase(fetchUser.fulfilled, (state, action) => action.payload);
  },
});

const todosSlice = createSlice({
  name: "todos",
  initialState: [] as Todo[],
  reducers: {
    addTodo: (state, action) => {
      state.push({
        id: Date.now(),
        text: action.payload.text,
        completed: false,
      });
    },
    toggleTodo: (state, action) => {
      const todo = state.find((t) => t.id === action.payload.id);
      if (todo) {
        todo.completed = !todo.completed;
      }
    },
    removeTodo: (state, action) => {
      return state.filter((t) => t.id !== action.payload.id);
    },
  },
});

// Combine reducers
const rootReducer = combineReducers<AppState>({
  user: userSlice.reducer,
  todos: todosSlice.reducer,
  loading: (state = false, action) => {
    if (action.type === fetchUser.pending) return true;
    if (
      action.type === fetchUser.fulfilled ||
      action.type === fetchUser.rejected
    )
      return false;
    return state;
  },
});

// Create store with middleware
const store = createSvelteStore(
  rootReducer,
  undefined,
  applyMiddleware(thunkMiddleware)
);

// Export store and actions
export { store };
export const actions = {
  user: { ...userSlice.actions, fetchUser },
  todos: todosSlice.actions,
};

2. Use in your Svelte components

<!-- App.svelte -->
<script lang="ts">
  import { store, actions } from './store';

  // Access state reactively
  let user = $derived(store.state.user);
  let todos = $derived(store.state.todos);
  let loading = $derived(store.state.loading);

  // Dispatch actions
  function addUser(text) {
    store.dispatch(actions.todos.addTodo({ text }));
  }

  function toggleTodo(id) {
    store.dispatch(actions.todos.toggleTodo({ id }));
  }

  function loadUser() {
    store.dispatch(actions.user.fetchUser(1));
  }
</script>

<div>
  <h1>Svelte Redux-Esque App</h1>

  {#if loading}
    <p>Loading user...</p>
  {:else if user}
    <h2>Welcome, {user.name}!</h2>
  {:else}
    <button on:click={loadUser}>Load User</button>
  {/if}

  <div>
    <h3>Todos</h3>
    <ul>
      {#each todos as todo}
        <li>
          <input
            type="checkbox"
            checked={todo.completed}
            on:change={() => toggleTodo(todo.id)}
          />
          <span class:completed={todo.completed}>{todo.text}</span>
        </li>
      {/each}
    </ul>
    <input placeholder="Add todo" on:keydown|enter={(e) => {
      if (e.target.value) {
        addUser(e.target.value);
        e.target.value = '';
      }
    }} />
  </div>
</div>

<style>
  .completed {
    text-decoration: line-through;
    opacity: 0.6;
  }
</style>

📖 Complete Documentation

For detailed information about all features, API reference, and advanced patterns, please visit the documentation.

🎯 Key Concepts

Store

Actions

Reducers

Selectors

Middleware

Utilities

🚀 Advanced Features

Async State Management

  • Handle API calls and async operations
  • Automatic loading and error state management
  • Learn more

State Persistence

  • Built-in localStorage/sessionStorage integration
  • SSR-safe persistence
  • Learn more

TypeScript Support

  • Full TypeScript support with comprehensive type definitions
  • Type-safe actions, reducers, and selectors
  • Learn more

🛠️ Best Practices

  • Use createSlice for most reducer creation
  • Keep state minimal and focused
  • Use selectors for derived state
  • Handle errors properly in async operations
  • Use createSvelteStore for Svelte components
  • Read best practices

🔄 Comparison with Redux

Feature Redux Redux-Esque (Svelte 5)
State Updates Immutable Svelte Runes
Reactivity Manual subscription Automatic with runes
Bundle Size Larger Smaller
Learning Curve Steeper Familiar to Redux users
Performance Good Optimized for Svelte

Learn more about the differences

🤝 Contributing

Contributions are welcome! Please read our contributing guidelines before submitting pull requests.

📄 License

MIT

Top categories

Loading Svelte Themes