Skip to content

stadux/stadux

Repository files navigation

stadux

npm bundle size

A state manager that is highly inspired by Effector but much simpler with only about 100 lines of code.

Introduction

Stadux is an multi-store state manager for Javascript apps (React/React Native/Node.js), that allows you to manage data in complex applications without the risk of inflating the monolithic central store, with clear control flow, good type support and high capacity API. Stadux supports TypeScript out of the box.

Core concepts

  • Event Event is a function that describe what happened.
  • Store Store is the unit of state that you want to manage and will update according to the event.
  • Effect Side effect is hard to manage and effect will fire event when side effect start, done or failed.

That's all the connect that you need to know!

Installation

npm install --save stadux
# or
yarn add stadux

API

createEvent

// create event with `string` type of payload
const sayHi = createEvent<string>()

// you can watch for the event to happen
sayHi.watch(console.log)

// fire the event with payload
sayHi('Peter') // Peter
sayHi('Drew')  // Drew

createStore

const increment = createEvent('increment')
const decrement = createEvent('decrement')
const resetCounter = createEvent('reset counter')

const counter = createStore(0) // create store with init value
  .on(increment, state => state + 1) // update when event fired
  .on(decrement, state => state - 1)
  .reset(resetCounter) // reset when event fired

counter.watch(console.log) // you can also watch to the store

increment()    // State: 1
decrement()    // State: 0
decrement()    // State: -1
resetCounter() // State: 0
increment()    // State: 1

// use `gestState` to get value in store
const count = counter.getState()
// you can also use select to map value in the store
const greaterThan10 = counter.select(v => v > 10)

createEffect

type Todo = { name: string }
// build an effect to fetch API
const fetchTodoList = createEffect<
  { token: string }, // params of effect function
  Todo[] // response
>(({ token }) => axios.get(`https://todos?token=${token}`).then(v => v.data))

const todoList = createStore<{
  todos: Todo[]
  loading: boolean
  error: string
}>({ todos: [], loading: false, error: '' })
  .on(fetchTodoList.start, (state, payload) => ({
    ...state,
    loading: true,
    error: '',
  }))
  .on(fetchTodoList.done, (state, { result }) => ({
    ...state,
    todos: result,
    loading: false,
    error: '',
  }))
  .on(fetchTodoList.fail, (state, { error }) => ({
    ...state,
    loading: false,
    error: error.message,
  }))

// after fetchTodoList been called, it will fire `fetchTodoList.start`
// when fetch todo list succeed, it will fire `fetchTodoList.done` event with respond value
// when fetch todo list failed, it will fire `fetchTodoList.fail` event with error reason
fetchTodoList({ token: '' })

Use in React

npm install --save stadux-react
# or
yarn add stadux-react
const increment = createEvent()
const decrement = createEvent()
const resetCounter = createEvent()
const counter = createStore(0)
  .on(increment, state => state + 1)
  .on(decrement, state => state - 1)
  .reset(resetCounter)

const CountComponent = () => {
  const count = useStore(counter)

  return <div>Count is: {count}</div>
}