Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dogstore #93

Open
ahdinosaur opened this issue May 31, 2018 · 0 comments
Open

dogstore #93

ahdinosaur opened this issue May 31, 2018 · 0 comments

Comments

@ahdinosaur
Copy link
Member

a random idea to re-write the core of dogstack

dogstore

opinionated redux using a composition of tiny modules that do one thing well:

  • redux-action-registry
  • reselect-registry
  • redux-state-reactor in progress
  • feathers-action@3
  • redux-action-query
  • modified redux-thunk

redux-action-registry

no more importing redux action creators around,

dispatch an action with an action creator name and arguments,

a friendly middleware will to create and dispatch the action for you.

const { createStore, applyMiddleware } = require('redux')
const { action, middleware: actionRegistryMiddleware } = require('redux-action-registry')
const reducer = require('./reducer')

const actions = {
  yoga: () => ({ type: 'YOGA' }),
  eat: (food) => ({ type: 'EAT', food })
  sleep: (length) => ({ type: 'SLEEP', length })
}

const store = createStore(
  reducer,
  applyMiddleware(
    actionRegistryMiddleware(actions)
  )
)

store.dispatch(action('yoga'))
store.dispatch(action('eat', 'burritos'))
store.dispatch(action('sleep', '10h))

source hints:

function action (actionCreator, ...args) {
  return { actionCreator, args }
}

reselect-registry

no more importing reselect selectors around,

create selectors from the names of other selectors.

const _ = require('lodash')
const combineSelectors = require('reselect-registry')

const usersData = state => state.users
const thingsData = state => state.things

// reselect.createSelector
const thingsByUsers = [
  'things',
  things => _.groupBy(things, 'userId')
]

const users = [
  'users',
  'thingsByUser',
  (users, thingsByUser) => {
    return _.mapValues(users, user => {
      const things = thingsByUser[user.id]
      return _.assign(user, { things })
    })
  }
)

// reselect.createStructuredSelector
const usersPageProps = {
  users: true
}

const selectors = combineSelectors({
  usersData,
  thingsData,
  thingsByUsers,
  users,
  usersPageProps
})

redux-state-reactor

reactors are similar to selectors,

they receive the state and return either an action or false.

const { createStore, applyMiddleware } = require('redux')
const { middleware: actionReactorMiddleware } = require('redux-action-reactor')

const actions = require('./actions')

const reducer = (state = {}, action) => {
  if (action.type === 'AUTHENTICATE_START') {
    return Object.assign(state, { isAuthenticating: true })
  } else if (action.type === 'AUTHENTICATE_COMPLETE') {
    return Object.assign(state, { isAuthenticating: false, isAuthenticated: true })
  }
  /* ... */
}

const authenticationReactor = state => {
  if (state.isAuthenticated) return false
  if (state.isAuthenticating) return false // to avoid reactor cycle
  return actions.authenticate()
}

const reactors = [
  authenticateReactor
]

const store = createStore(
  reducer,
  applyMiddleware(
    actionReactorMiddleware(authenticationReactor)
  )
)

// with empty state, will automatically start authenticating!

feathers-action@3

good ideas from feathers-action@2:

  • keep all request state in feathers key
  • design for testing

changes:

  • id of request is hash of arguments
  • use feathers-thunk instead of redux-observable
  • service method call api
    • things.get(id, params), etc
    • return promises
  • service listener api
    • things.onCreated({ dispatch, filter })
    • listeners are implicitly restricted by feathers channels
    • filter using similar techniques as feathers-reactive

redux-action-query

  • smart dependent queries
  • assume request state is stored in stateKey
    • status
      • start
      • error
      • done
    • result
    • error
const actions = require('./actions')

const queries = [
  {
    name: 'users',
    action: (state) => actions.fetchUsers()
  }
  {
    name: 'thingsForUsers',
    dependencies: [
      'users'
    ],
    action: (state) => {
      const users = state.users
      return action.fetchThingsForUsers(users)
    }
  }
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant