All Projects → tkh44 → Smitty

tkh44 / Smitty

Licence: mit
Tiny flux implementation built on mitt

Programming Languages

javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to Smitty

AndroidFluxPractice
Android Flux Practice
Stars: ✭ 51 (-75.71%)
Mutual labels:  flux, flux-architecture
mini-swift
Minimal Flux architecture written in Swift.
Stars: ✭ 40 (-80.95%)
Mutual labels:  flux, flux-architecture
react-workshops
Online react workshops
Stars: ✭ 36 (-82.86%)
Mutual labels:  flux, flux-architecture
redux-reducer-async
Create redux reducers for async behaviors of multiple actions.
Stars: ✭ 14 (-93.33%)
Mutual labels:  flux, flux-architecture
Fleur
A fully-typed, type inference and testing friendly Flux Framework
Stars: ✭ 74 (-64.76%)
Mutual labels:  flux, flux-architecture
fluxiny
~1K implementation of flux architecture
Stars: ✭ 77 (-63.33%)
Mutual labels:  flux, flux-architecture
Goes
Go Event Sourcing made easy
Stars: ✭ 144 (-31.43%)
Mutual labels:  flux, flux-architecture
Vuex-Alt
An alternative approach to Vuex helpers for accessing state, getters and actions that doesn't rely on string constants.
Stars: ✭ 15 (-92.86%)
Mutual labels:  flux, flux-architecture
Nanoflux
A very lightweight and dependency-free Flux implementation
Stars: ✭ 56 (-73.33%)
Mutual labels:  flux, flux-architecture
Delorean
An Agnostic, Complete Flux Architecture Framework
Stars: ✭ 748 (+256.19%)
Mutual labels:  flux, flux-architecture
fluxy
Fluxy is a Flux architecture implementation written in Kotlin.
Stars: ✭ 25 (-88.1%)
Mutual labels:  flux, flux-architecture
Hover
A very lightweight data store with action reducers and state change listeners.
Stars: ✭ 97 (-53.81%)
Mutual labels:  flux, flux-architecture
nanoflux-fusion
Redux-like extension for Nanoflux
Stars: ✭ 15 (-92.86%)
Mutual labels:  flux, flux-architecture
Firedux
🔥 🐣 Firebase + Redux for ReactJS
Stars: ✭ 148 (-29.52%)
Mutual labels:  flux, flux-architecture
universal-routed-flux-demo
The code in this repo is intended for people who want to get started building universal flux applications, with modern and exciting technologies such as Reactjs, React Router and es6.
Stars: ✭ 31 (-85.24%)
Mutual labels:  flux, flux-architecture
Fluxxan
Fluxxan is an Android implementation of the Flux Architecture that combines concepts from both Fluxxor and Redux.
Stars: ✭ 80 (-61.9%)
Mutual labels:  flux, flux-architecture
Fluxcapacitor
This is what makes the Flux design pattern possible.
Stars: ✭ 126 (-40%)
Mutual labels:  flux, flux-architecture
Qframework
Unity3D System Design Architecture
Stars: ✭ 2,326 (+1007.62%)
Mutual labels:  flux
Multi Tenancy
Flux v1: Manage a multi-tenant cluster with Flux and Kustomize
Stars: ✭ 180 (-14.29%)
Mutual labels:  flux
Fluxible
A pluggable container for universal flux applications.
Stars: ✭ 1,811 (+762.38%)
Mutual labels:  flux

smitty
smitty

Tiny flux implementation built on mitt

smitty

npm version Build Status codecov

Install

npm install -S smitty

Basic Usage

import { createStore } from 'smitty'

// Create a store with initial state
const initialState = { count: 0 }
const store = createStore(initialState)

store.createActions({
  add: 'count/ADD'
})

// add a reducer
store.handleActions({
  [store.actions.add]: (state, e, type) => {
    // increment foos by amount
    return Object.assign({}, state, { count: state.count + e.amount })
  },
  '*': (state, e, type) => {
    // '*' can be used for all kinds of fun stuff
    console.log(e, type)
    if (type === 'count/ADD') {
      //...do something
    }
    return state
  }
})

store.actions.add({ amount: 5 })

console.log(store.state)  // logs `{ count: 5 }`

Demos (v2)

Demos (v1)


Usage with Preact and React


API

createStore(initialState: any)

Arguments

initialState: any required: Determines the shape and initial state of your store. Can be of any type that you choose.

Returns

Store: Store Store


Store

emit: (function)

arguments

type: (string | function)

  • [string], type determines which reducers are called.

    const store = createStore(0)
    store.handleActions({
      add: function (state, payload) {
        return state + payload
      }
    })
    console.log(store.state) // logs 0
    store.emit('add', 1)
    console.log(store.state) // logs 1
    
  • [function] type becomes an action creator that is passed 1 argument

    This is useful to emit multiple actions from a single emit call.

    const store = createStore(0)
    store.handleActions({
      add: function (state, payload) {
        return state + payload
      }
    })
    function asyncAction (emit, state) {
      emit('add', 1)
      console.log(state) // logs 1
      setTimeout(() => {
        emit('add', 1)
        console.log(state) // logs 3
      }, 100)
      emit('add', 1)
      console.log(state) // logs 2
    }
        ```
    
    

payload: (any) optional

payload to pass to your reducer

const store = createStore({ name: 'Arrow' })
store.handleActions({
  'update/NAME': function (state, payload) {
    // I really don't care if you return a new state
    // Nobody is judging. Do what your ❤️ tells you.
    // Just be consistent
    return Object.assign({}, state, payload)
  }
})
console.log(store.state) // logs { name: 'Arrow' }
store.emit('update/NAME', { name: 'River' })
console.log(store.state) // logs { name: 'River' }

createActions(): (function)

arguments

actionMap: (object)

Object where key is the action creator's name and the value can be of type string or function.

If the value is a string, an action creator is attached to store.actions as a function that accepts one argument, payload.

store.createActions({
  add: 'count/ADD'
})

// The following are functionally equivalent
store.actions.add(1)

store.emit('count/ADD', 1)

Action creators with a string value can be used as the key in your actionMap in handleActions.

store.createActions({
  add: 'count/ADD'
})

// add a reducer
store.handleActions({
  [store.actions.add]: (state, e, type) => {
    // increment foos by amount
    return Object.assign({}, state, { count: state.count + e.amount })
  }
})

store.actions.add({ amount: 5 })

console.log(store.state)  // logs `{ count: 5 }`

If the value is a function, it must be a function that returns an action creator. For async action creators.

store.createActions({
  add: (amount) => {
    return (store) => {
      setTimeout(() => {
       store.emit('count/ADD', amount)
      }, 16)
    }
  }
})

store.actions.add(1)

handleActions(): (function)

arguments

handlerMap: (object)

Object with keys that correspond to action types passed to emit

When an event is emitted and the key matches the type the reducer is invoked with 3 arguments.

  • state: (any) the store's state getter
  • payload (any) the payload that was emitted
  • type (string) the type that was emitted
const store = createStore({ color: 'blue', hovered: false })
store.handleActions({
  'merge': function (state, payload) {
    return Object.assign({}, state, payload)
  },
  'overwrite': function (state, payload) {
    return payload
  },

  // Could do the same in one
  // If you really miss redux do this and put a switch statement
  '*': function(state, payload, type) {
    return type === 'merge' ? Object.assign({}, state, payload) : payload
  }
})
console.log(store.state) // logs { color: 'blue', hovered: false }
store.emit('merge', { color: 'red' })
console.log(store.state) // { color: 'red', hovered: false }
store.emit('overwrite', { color: 'green', hovered: true, highlighted: false })
console.log(store.state) // { color: 'green', hovered: true, highlighted: false 

actions: (object)

Map of all the actions created in store.createActions

This is convenient so that you do not have to deal with action imports across your app.

on: (function)

Convenience shortcut for mitt.on.

off: (function)

Convenience shortcut for mitt.off.


Action Creator Detailed Example

You can pass a function to emit in order to create an action creator

running example

import { createStore } from 'smitty'

// Create a store with initial state
const initialState = {}
const store = createStore(initialState)

// add our reducer
store.handleActions({
  'api/GET_ROOM': (state, { id, res }) => {
    return {
      ...state,
      [id]: {
        ...state[id],
        ...res.data
      }
    }
  }
})

// create our action creators
const actions = {
  requestRoom (id) {
    return async (emit, state) => {
      emit('REQUEST_ROOM', { id, res: { data: { id } } })
      const res = await window.fetch(`https://api.mysite.com/${id}`)
      res.data = await res.json()
      emit('REQUEST_ROOM', { id, res })
    }
  }
}

// When calling emit with a function argument, the function will be called with `emit` and `state` as arguments
const result = store.emit(actions.requestRoom('1a'))

// Return whatever you like from your action creator
console.log(result) // logs "Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}"

// After the fetch call, `REQUEST_ROOM` is fired a second time with our response data
result.then(() => console.log(store.state)) // logs `{ 1a: { id: '1a', title: 'My Room' }``

Class As Reducer

Reducers are iterated with for (let type in reducer) {...} with no obj.hasOwnProperty check so this works.

const store = createStore({ foo: 5 })

class HistoryReducer {
  constructor (initialHistory = []) {
    this.history = createStore(initialHistory)
    this.history.handleActions({
      update: (state, e) => {
        state.push(e)
      }
    })
  }

  onUpdate (state, e, type) {
    this.history.emit('update', { state, e, type })
  }
}

HistoryReducer.prototype['foo/ADD'] = function (state, e, type) {
  state.foo += e.foo
  this.onUpdate(state, e, type)
}

const historyReducer = new HistoryReducer([])
store.handleActions(historyReducer)

store.emit('foo/ADD', { foo: 5 })
console.log(store.state.foo) // logs 10
store.emit('foo/ADD', { foo: 7 })
console.log(store.state.foo) // logs 17
console.log(historyReducer.history.state)
// logs
// [
//   { state: { foo: 10 }, e: { foo: 5 }, type: 'foo/ADD' },
//   { state: { foo: 17 }, e: { foo: 7 }, type: 'foo/ADD' }
// ]

Thanks

Thanks to developit for mitt and the project structure.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].