1.0.4 • Published 4 years ago

rewrapped v1.0.4

Weekly downloads
1
License
MIT
Repository
github
Last release
4 years ago

Rewrapped

npm version Build Status Coverage Status

Typescript / Javascript Redux dispatcher, action and reducer wrapper with a special emphasis on:

  • Minimal boilerplate for maximum readability and ergonomics
  • Complete typesafety for Typescript and strong autocompletion / refactoring support for Javascript
  • Immutable updates through a mutable API powered by Immer
  • Support for easy interop with and incremental migration from traditional Redux reducers.

NOTE: Below code samples are written in Typescript.Javascript users can remove type annotations while still levaraging the IDEs Typescript interpreter (VSCode provides best support)

Basic Usage

import { manageModule } from 'rewrapped';

export const todoModule = manageModule({
  todos: new Array<{ todo: string, done: boolean }>(),
  editingIndex: -1,
})({
  Add: (state, todo: string) => state.todos.push({ todo, done: false }),
  Update: (state, todo: string) => state.todos[state.editingIndex].todo = todo,
  Remove: (state, index: number) => state.todos.splice(index, 1),
  ToggleDone: (state, index: number) => state.todos[index].done = !state.todos[index].done,
  EditIndex: (state, index: number) => state.editingIndex = index,
});

todoModule.Add('Relax'); // dispatch

Full Demo: Typescript | Javascript

Setup

npm i redux react-redux rewrapped
npm i --dev @types/redux @types/react-redux
import { createStore, combineReducers } from 'redux';
import { configureRewrapped } from 'rewrapped';

const store = createStore(combineReducers({
  todo: todoModule.reducer,
  //... other module's reducers...
}));
configureRewrapped({
  store,
});

Async-updates

To update state after a promise settles, new actions can be dispatched.

import { manageModule } from 'rewrapped';

const todoModule = manageModule({
  todos: new Array<string>(),
})({
  AddTodo: (state, todo: string) => state.todos.push(todo),
  SaveNewTodo: (state, todo: string) => {
    return () => remotelySaveTodo(todo)
      // .then(res => state.todos.push(res.savedTodo)) // Won't work: directly updating the state variable
      .then(res => todoModule.AddTodo(res.savedTodo)) // Will work: dispatching a new action
  },
});

Direct Updates

Some state updates are straightforward and repetitive (such as storing various collections retrieved from an API). In such cases, you can bypass writing a dedicated module function by using the built-in directUpdate() function as follows.

todoModule.directUpdate(s => s.todos).assign(todosReceivedFromApi)

NOTE: Using directUpdate() will compromise testability and discoverability because it will de-centralize your state logic. Use this function sparingly for simple updates. Prefer creating dedicated module functions.

Dispatcher-tags

Your debugging experience can be improved by enforcing that a tag (identifying the source of the dispatch) be supplied when dispatching actions. While this has no effect on functionality, the library will prefix the action type with this tag providing greater transparency in the Redux devtools. To enforce dispatcher tags, use manageModuleTagged instead of manageModule when creating a module. (Note that, for webpack users, it may be convenient to use the __filename as the dispatcher tag)

import { manageModuleTagged } from 'rewrapped';

const myModule = manageModuleTagged({
  prop: '',
})({
  UpdateProp: (state, prop: string) => state.prop = prop,
});

myModule.UpdateProp('MyComponent', 'Hello'); // Here the dispatcher tag is 'MyComponent'. The payload is 'Hello'.

Waiting for dispatch to complete

All dispatches will return a promise

  todoModule.AddTodo('Work out').then(r => console.log(`Returned ${r.returned}, Produced: ${r.produced}`))

Deriving payload type from initial state

It can be useful to extract the initialState into its own variable so that that object can be referenced when declaring the payload type.

const initialState = {
  some: {
    thing: {
      propOne: '',
      propTwo: false,
    }
  }
};

export const myModule = manageModule(initialState)({
  UpdateThing: (state, thing: typeof initialState.some.thing) => state.some.thing = thing,
});

myModule.UpdateThing({ propOne: 'hello', propTwo: true, });
1.0.4

4 years ago

1.0.3

4 years ago

1.0.2

4 years ago

1.0.1

4 years ago

1.0.0

4 years ago