tunnckoCore / ideas

:notebook: My centralized place for ideas, thoughts and todos. Raw, PoC implementations and so on... :star:
http://j.mp/1stW47C
6 stars 0 forks source link

state management - fragmented state / sliced state #104

Open tunnckoCore opened 6 years ago

tunnckoCore commented 6 years ago

as seen in Hyperapp, which pretty great idea.

old code, but just for backup here

/**
 *
 * @param {*} options
 */

/* eslint-disable max-statements, no-param-reassign, no-consistent-return, no-return-assign */

const update = partialState => state => Object.assign({}, state, partialState)

function elmaz(options) {
  const opts = Object.assign({}, options)
  let STATE = Object.assign({}, opts.state)

  const globalActions = {}
  const hasOwn = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key)
  const prev = []

  function initActions(state, actions, raw) {
    Object.keys(raw).forEach(name => {
      if (typeof raw[name] === 'object' && hasOwn(state, name)) {
        prev.push(name)
        initActions(state[name], actions[name] || (actions[name] = {}), raw[name])
      } else if (typeof raw[name] === 'function') {
        actions[name] = (...args) => {
          if (hasOwn(state, name)) {
            const result = raw[name]({ state: state[name], actions, update }, ...args)

            // so, reducer (returned REPLACES STATE directly)
            // so, use the `update` helper like `({ update }) => update({ hi: 123 })
            if (typeof result === 'function') {
              state[name] = result(state[name])
              STATE = Object.assign({}, STATE, state[name])
              return state[name]
            }

            return result
          }

          const upper = prev.shift()

          if (hasOwn(STATE, upper)) {
            const result = raw[name]({ state: STATE[upper], actions, update }, ...args)

            // so, reducer (returned REPLACES STATE directly)
            // so, use the `update` helper like `({ update }) => update({ hi: 123 })
            if (typeof result === 'function') {
              STATE[upper] = result(STATE[upper])
              return STATE[name]
            }

            return result
          }

          const result = raw[name]({ state: STATE, actions, update }, ...args)

          // so, reducer (returned REPLACES STATE directly)
          // so, use the `update` helper like `({ update }) => update({ hi: 123 })
          if (typeof result === 'function') {
            STATE = result(STATE)
            return STATE
          }

          return result
        }
      }
    })
  }

  initActions(STATE, globalActions, opts.actions)

  return globalActions
}

const res = elmaz({
  state: {
    hello: 'world',
    buddy: {
      hi: 'zazzy',
      todo: {
        list: [],
        count: 0,
        done: 0,
      },
    },
  },
  actions: {
    foo: ({ state, actions }, ...args) => {
      console.log('foo action', state)
      console.log('========================')
    },
    bar: ({ state }) => {
      console.log('bar action', state)
      console.log('========================')
    },
    buddy: {
      some: ({ state }) => {
        console.log('buddy.some action', state)
        console.log('========================')

        // should replace the whole `state.buddy` state,
        // not the state of the app
        return (/* state */) => ({ hi: 'hello' })
      },
      xxx: ({ state }) => {
        console.log('buddy.xxx action', state)
        console.log('========================')
      },
      todo: ({ state, actions }) => {
        console.log('====')
        console.log('buddy.todo state:', state)
        console.log('todo acts:', actions)
        console.log('======================== todo end')
        return update({ damn: true })
      },
    },
  },
})

// res.buddy.some()
// res.buddy.xxx()
res.buddy.todo()
res.foo()

// console.log(res)