Unified State Management for Angular, Vue, React and Svelte

Universal model is a unified state management solution for the most popular modern Web UI frameworks: Angular, React, Svelte and Vue.

This is image title

The Universal model is composed of a store, states, actions, selectors and services that are the same for every UI framework — only view parts differ.

Universal model is best demonstrated by an example.

1. Create initial state

export interface Todo {
  id: number;
  name: string;
  isDone: boolean;
}

export default {
  todos: [] as Todo[],
  shouldShowOnlyUnDoneTodos: false,
  isFetchingTodos: false,
  hasTodosFetchFailure: false
};

2. Create state selectors

const createTodoListStateSelectors = <T extends State>() => ({
  shownTodos: (state: T) =>
    state.todosState.todos.filter(
      (todo: Todo) =>
        (state.todosState.shouldShowOnlyUnDoneTodos && !todo.isDone) ||
        !state.todosState.shouldShowOnlyUnDoneTodos
    ),
  todoCount: (state: T) => state.todosState.todos.length,
  unDoneTodoCount: (state: T) => state.todosState.todos.filter((todo: Todo) => !todo.isDone).length
});

3. Create a store

const initialState = {
  todosState: createSubState(initialTodoListState)
};

export type State = typeof initialState;

const todoListStateSelectors = createTodoListStateSelectors<State>();

const selectors = combineSelectors<State, typeof todoListStateSelectors>(
  todoListStateSelectors
);

export default createStore<State, typeof selectors>(initialState, selectors);

4. Create some actions

export async function fetchTodos(): Promise<void> {
  const { todosState } = store.getState();

  todosState.isFetchingTodos = true;
  todosState.hasTodosFetchFailure = false;

  try {
    todosState.todos = await todoService.tryFetchTodos();
  } catch (error) {
    todosState.hasTodosFetchFailure = true;
  }

  todosState.isFetchingTodos = false;
}


export function removeTodo(todoToRemove: Todo): void {
  const { todosState } = store.getState();
  todosState.todos = todosState.todos.filter((todo: Todo) => todo !== todoToRemove);
}


export function toggleIsDoneTodo(todo: Todo): void {
  todo.isDone = !todo.isDone;
}

5. Create your view

5.1 React version:

const TodoListView = () => {
  const [{ todosState }, { shownTodos }] = store.getStateAndSelectors();
  store.useStateAndSelectors([todosState], [shownTodos]);

  useEffect(() => {
    fetchTodos();
  }, []);

  let todoListContent;

  if (todosState.isFetchingTodos) {
    todoListContent = <div>Fetching todos...</div>;
  } else if (todosState.hasTodosFetchFailure) {
    todoListContent = <div>Failed to fetch todos</div>;
  } else {
    const todoListItems = shownTodos.value.map((todo: Todo) => (
      <li key={todo.id}>
        <input
          id={todo.name}
          type="checkbox"
          defaultChecked={todo.isDone}
          onChange={() => toggleIsDoneTodo(todo)}
        />
        <label>
          {todo.name}
        </label>
        <button onClick={() => removeTodo(todo)}>Remove</button>
      </li>
    ));

    todoListContent = <ul>{todoListItems}</ul>;
  }

  return (
    <div>
      {todoListContent}
    </div>
  );
};

5.2 Vue 3+ version:

<template>
  <div>
    <div v-if="todosState.isFetchingTodos">Fetching todos...</div>
    <div v-else-if="todosState.hasTodosFetchFailure">Failed to fetch todos</div>
    <ul v-else>
      <li v-for="todo in shownTodos">
        <input :id="todo.name" type="checkbox" :checked="todo.isDone" @click="toggleIsDoneTodo(todo)" />
        <label :for="todo.name">{{ userName }}: {{ todo.name }}</label>
        <button @click="removeTodo(todo)">Remove</button>
      </li>
    </ul>
  </div>
</template>

<script lang="ts">
export default {
  setup(): object {
    const [{ todosState }, { shownTodos }] = store.getStateAndSelectors();
    onMounted(() => {
      fetchTodos();
    });
    return {
      todosState,
      shownTodos,
      removeTodo,
      toggleIsDoneTodo
    };
  }
};
</script>

Resources

For more information, API, and examples, visit:

Thank you for reading!

#angular #vue #react #svelte

Unified State Management for Angular, Vue, React and Svelte
6.20 GEEK