0.1.0 • Published 4 years ago

retux v0.1.0

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

Retux

npm-version npm bundle size

Commitizen friendly Conventional Commits JavaScript Style Guide code style: prettier

Core library of Retux, a minimalist declarative type-safe(strongly-typed) scalable Redux architecture.

Features

  • Minimalist. Retux reduces huge volume of boilerplate code while still gaining better type-infer and auto-completion.
  • Declarative. Action-First desgin instead of Action-Creator-Fisrt makes it clean, less-hacking and easy to read for new contributors(including future-self!).
  • Type-safe(strongly-typed). Retux enforces strict typings. With utilities of Retux you will never lose the strictness of typings while enjoying great flexibility.
  • Scalable. A Retux module can be easily split into isomorphic sub-modules. Retux can also optionly leverage the power of meta-programming on modern engine for further performance boost.

Installation

  • yarn: yarn add retux
  • npm: npm add retux

Usage

See official guide.

API

See docs.

At First Glance

This is the basic structure of Retux architecture(Others see examples).

import { createStore } from 'redux'
import { CreateActionCatalog, ActionHandlers, createReducer } from 'retux'

// All actions of a module are defined here.
// This is the core of Retux design.
// Other infomation will be extracted from Action Catalog.
export type ActionCatalog = CreateActionCatalog<{
  INCREMENT: {
    payload: {
      // Comments will also be displayed on the intellisense panel
      /** default 1 */
      step?: number
    }
  }
  DECREMENT: {
    payload: {
      /** default 1 */
      step?: number
    }
  }
}>

export const initState = {
  count: 0
}

export type State = typeof initState

// Action Handlers can be easily splited.
export const actionHandlers: ActionHandlers<State, ActionCatalog> = {
  // Any missing or mistyped action will be caught by ts compiler.
  INCREMENT: (state, { payload: { step = 1 } }) => ({
    count: state.count + step
  }),
  DECREMENT: (state, { payload: { step = 1 } }) => ({
    count: state.count - step
  })
}

// Now in the store root:

const reducer = createReducer(initState, counterActionHandlers)

const store = createStore(reducer)

store.subscribe(() => console.log(store.getState()))

// Actions are strongly typed. Any mistyped name is caught by ts compiler.
store.dispatch({ type: 'INCREMENT' })

// Payload and meta are also strongly typed with the action type.
store.dispatch({ type: 'DECREMENT', payload: { step: 10 } })

Actions

If we need all the actions:

import { Action } from 'retux'

export type ActionCatalog = CreateActionCatalog<{
  ACTION1: { payload: boolean }
  ACTION2: { payload: number, meta?: boolean }
  ACTION3: { payload: { val: string } }
}>

type ModuleActions = Action<ActionCatalog>

// single action
type ActionIncrement = Action<ActionCatalog, 'ACTION1'>

Notice ModuleActions will be

type ModuleActions =
  | { type: 'ACTION1', payload: boolean }
  | { type: 'ACTION2', payload: number, meta?: boolean }
  | { type: 'ACTION3', payload: { val: string } }

instead of

type ModuleActions = {
  type: 'ACTION1' | 'ACTION2' | 'ACTION3',
  payload: boolean | number | { val: string }
  meta?: boolean | undefined
}

Action Creators

Retux is Action-First. All Action Creators are generated from Actions.

import { createActionCreators } from 'retux'

const action = createActionCreators<ActionCatalog>(actionHandlers)

dispatch(action.ACTION1(true))

That's it! Later on if you want to replace an action with thunk etc.

const action = createActionCreators<ActionCatalog>(
  actionHandlers,
  {
    ACTION1: (payload: boolean): MyThunkAction<'ACTION1'> =>
      dispatch => dispatch({ type: 'ACTION1', payload })
  }
)

Retux also offers proxyActionCreators for modern engines which does the same thing except action creators are lazy created on first visit.

See the guide for all the features of Retux.