redax

0.0.0 • Public • Published

Redax

Redax combines your actions & reducers to reduce the amount of files you'll need open, and amount of code you have to write - no more searching through dozens of files to find the reducer that matches your action, and no more constants for action types.

Redax also lets you access the entire state tree from every action so that you can easily store it in local storage, reset the entire state, or update multiple collections of data easily.

The redax Store has a very useful map function to connect your store directly to a component's props. No more need to manually add and remove listeners for state changes, or wrap your application with a provider. Because redax uses immutablejs it internally difs your previous and next state, so that components will only update if a change has been made.

By default redax will allow you to chain actions and handle asynchronous requests as calls made to actions from inside an action are deferred until the action has been resolved.

Usage

Create a store

A store's default state is an immutablejs Map. We call our setCount action after creation to set the initial count value, but this could set the entire initial state of your application, or be used to reset the state if you need to do so (which you should do with state.clear()).

// store.js
 
import { Store } from 'redax';
import * as actions from './actions';
 
const store = new Store(
  // Object containing our actions
  actions
);
 
store.actions.setCount();
 
export default store;

Actions

Every action is also a reducer, so they must all return the state. The state in each action is the entire state of the store. It's recommended that you use setIn and deleteIn for grouping related data (example a little further down).

// actions.js
 
// Used to set the initial count value
export function setCount (state) {
  return state.set('count', 0);
}

Combine multiple action files

Use Object.assign or similar, e.g. _.extend, to combine multiple sets of actions.

// store.js
 
import * as login from './login';
import * as todo from './todo';
 
const store = new Store(
  Object.assign(
    {},
    login,
    todo
  )
);

Chaining actions

Notice that the incrementThenDecrementTwice action calls the decrement action twice. The decrement calls will be deferred until incrementThenDecrementTwice is resolved, this means that you can easily chain actions, and handle asynchronous requests.

// actions.js
 
export function decrement (state) {
  return state.set('count', state.get('count') - 1);
}
 
export function incrementThenDecrementTwice (state) {
  this.actions.decrement();
  this.actions.decrement();
  return state.set('count', state.get('count') + 1);
}

Asynchronous example

Here we make an asynchronous request and then call either our success or failure action. You can access the store's actions via this.actions if you do not have access to the store itself. Notice how we group our state into login and auth because we have access to the entire state.

// login.js
 
export function loginSuccess(state, response) {
  const login = state.get('login', Map())
    .delete('loading')
    .delete('error');
 
  return state.set('login', login)
    .setIn(['auth', 'token'], response);
}
 
export function loginFailure(state, error) {
  const login = state.get('login', Map())
    .delete('loading')
    .set('error', error);
 
  return state.set('login', login)
    .deleteIn(['auth', 'token']);
}
 
export function login(state, username, password) {
  const login = state.get('login', Map())
    .set('loading', true)
    .delete('error');
 
  request('/login/')
    .data({username, password})
    .send()
    .then(this.actions.loginSuccess, this.actions.loginFailure);
 
  return state.set('login', login)
    .deleteIn(['auth', 'token']);
}

Connecting your store state to your components

Connect your store's state to your components easily with store.map. Notice that we do not need to connect our actions to our component as these are automatically dispatched on call.

// component.js
 
import store from './store';
// Destructuring our actions from the store
const { actions: { incrementThenDecrementTwice } } = store;
 
class Component extends React.Component {
  render() {
    const { count } = this.props;
 
    return (
      <button onClick={incrementThenDecrementTwice}>
        Count: {count}
      </button>
    );
  }
}
 
function stateToProps(state) {
  return {
    count: state.get('count')
  };
}
 
export default store.map(stateToProps).to(Component);

Package Sidebar

Install

npm i redax

Weekly Downloads

4

Version

0.0.0

License

MIT

Last publish

Collaborators

  • jakesidsmith