Wondering what’s next for npm?Check out our public roadmap! »

    rewrapped
    TypeScript icon, indicating that this package has built-in type declarations

    1.0.4 • Public • Published

    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, });

    Install

    npm i rewrapped

    DownloadsWeekly Downloads

    1

    Version

    1.0.4

    License

    MIT

    Unpacked Size

    420 kB

    Total Files

    23

    Last publish

    Collaborators

    • avatar