yax

Yet another store using redux. (Inspired by vuex and dva)

Usage no npm install needed!

<script type="module">
  import yax from 'https://cdn.skypack.dev/yax';
</script>

README

Yax (Yet Another Store)

NPM version NPM downloads Build Status Coverage Status Dependency Status Greenkeeper badge

Yet another store using redux. (Inspired by vuex and dva)

Demos & Plugins

  • yax-router: Router plugin for yax (Using react-router).
  • HackerNews: HackerNews clone built with Yax, based on dva-hackernews.

Getting Started

Install

$ npm install --save yax

Usage Example

import yax from 'yax';

const delay = ms => new Promise(resolve => setTimeout(resolve, ms));

const count = {
  state: 0,
  reducers: {
    addDone (state, payload) {
      return state + payload;
    },
    minusDone (state, payload) {
      return state - payload;
    }
  },
  actions: {
    async add ({ commit }, payload) {
      await delay(1);
      commit('addDone', payload);
    },
    async minus ({ commit }, payload) {
      await delay(1);
      commit('minusDone', payload);
    }
  }
};
const store = yax({
  modules: { count }
});

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

store.dispatch({
  type: 'count/add',
  payload: 2
});
store.dispatch({
  type: 'count/minus',
  payload: 1
});

Usage with React

import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import yax from 'yax';
import count from './count';
import App from './App';

const store = yax({
  modules: { count }
});

render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);

Usage with redux-persist

import yax from 'yax';
import { persistStore, autoRehydrate } from 'redux-persist';

const store = yax(options, autoRehydrate());

persistStore(store, { storage: Storage });

Usage with react-navigation

import yax, { compose, composeReducers, mapReducers } from 'yax';
import { StackNavigator } from 'react-navigation';

const AppNavigator = StackNavigator(AppRouteConfigs);
const initialAction = AppNavigator.router.getActionForPathAndParams('Login');
const initialState = AppNavigator.router.getStateForAction(initialAction);

const navReducer = (state = initialState, action) => {
  const nextState = AppNavigator.router.getStateForAction(action, state);
  return nextState || state;
};
const navEnhancer = createStore => (reducer, preloadedState, enhancer) => {
  const appReducer = composeReducers(
    reducer,
    mapReducers({
      nav: navReducer
    })
  );
  return createStore(appReducer, preloadedState, enhancer);
};
const store = yax({
  modules: { foo, bar }
}, compose(
  navEnhancer,
  otherEnhancers
));


// In modules with `commit`
import { NavigationActions } from 'react-navigation';

const LOGIN = NavigationActions.navigate({ routeName: 'Login' });
const BACK = NavigationActions.back();
...
commit(LOGIN, true);
commit(BACK, true);

API Reference

import yax, {
  // Redux original functions
  combineReducers,
  bindActionCreators,
  applyMiddleware,
  compose,
  // Yax helper functions
  composeReducers,
  mapReducers,
  mapState,
  mapActions
} from 'yax';

yax(options = {}, [enhancer])

  • options.state

    The root state object for the store.

  • options.reducers

    { [type: string]: Reducer }
    
    type Reducer = (state, payload) => state
    

    state will be module local state if defined in a module

  • options.actions

    { [type: string]: Action }
    
    type Action = ({ dispatch, commit, select }, payload) => Promise
    
    type dispatch = (type, payload, isRoot) => Promise
    type commit   = (type, payload, isRoot) => any
    

    isRoot=true will dispatch actions or commit reducers in the global namespace

    type select   = (Selector) => Selector(state, rootState)
    type Selector = (state, rootState) => any
    

    select() without Selector will return state

  • options.modules

    { [type: string]: Module }
    
    type Module = { state, reducers, actions, modules }
    
  • enhancer

    type StoreEnhancer = (next: StoreCreator) => StoreCreator
    

    redux store enhancer

composeReducers(...reducers)

const f = (state, action) => {};
const g = (state, action) => {};
// (state, action) => g(f(state, action), action)
const reducer = composeReducers(f, g);

mapReducers(reducers)

Like with combineReducers but composability. More

const foo = (state, action) => {};
const bar = (state, action) => {};
const reducer = mapReducers({ foo, bar });

mapState and mapActions

Used for react-redux connect

const App = ({ foo, bar, addFoo, addBar }) => {
  addFoo(payload);
  addBar(payload);
  return <span>{foo} / {bar}</span>;
};
connect(
  mapState({
    foo: 'foo/value',
    bar: 'bar/value'
  }),
  mapActions({
    addFoo: 'foo/add',
    addBar: 'bar/add'
  })
)(App);

Report a issue

License

yax is available under the terms of the MIT License.