1.0.0-alpha.7 • Published 6 years ago

redux-loop-composer v1.0.0-alpha.7

Weekly downloads
1
License
MIT
Repository
gitlab
Last release
6 years ago

Redux-loop composer

Easely create actions, handle reducers and it's side effects thanks to redux-loop

Quick start

npm i -s redux-loop-composer

1. Create a module

import loopModule from 'redux-loop-composer';

const loginModule = loopModule.create('login');

2. Export actions

export const login = (username, password) => loginModule.action('login').payload({ username, password });
export const loginSuccess = (user) => loginModule.action('loginSuccess').payload({ user });
export const loginFailure = (error) => loginModule.action('loginFailure').payload({ error });
export const logout = () => loginModule.action('logout').noPayload();
export const tokenExpired = () => loginModule.action('tokenExpired').noPayload();

3. Handle reducers

loginModule
    // initial state
    .reducer({
        logging: false,
        loginSuccess: false,
        user: null
    })
    .when('login')
    .evolve(() => ({ logging: true, loginSuccess: false })) // change state

    .when('loginSuccess')
    .evolve(({ user }) => ({ logging: false, loginSuccess: true, user })) // change state

    .when('loginFailure')
    .evolve(() => ({ logging: false, loginSuccess: false })) // change state

    .when(['logout', 'tokenExpired'])
    .overwrite(() => ({user: null})) // overwrite state

    .end(); // finish reducer composition

4. Schedule side effects

Handle side effects with redux-loop:

loginModule
    .sideEffects()

    .when('login')
    .run(loginService.login) // remote call
    .args(({ username, password }) => [username, password]) // extract arguments from current action payload
    .then(loginSuccess) // success action
    .catch(loginFailure) // failure action

    .when('loginSuccess')
    .action(showMessage) // simply dispatch another action
    .args('Login successful') // static argument passed to the new action

    .when('loginFailure')
    .action(showErrorMessage) // simply dispatch another action
    .args(({error}) => [error.message]) // extract arguments from current action payload

    .when('tokenExpired')
    .cmd(() => Cmd.action(showMessage('Session expired, please login again to proceed'))) // manually invoke Cmds

    .end(); // finish side effects composition

5. Add an module to the appliacation

const store = loopModule.app('example').addModule(loginModule).addModule(messageModule).compose();

6. Access the state from a module

Direct access:

store.subscribe(() => {
    const loginState = loginModule.fromStore(store.getState()).getState();
    const user = loginState.user;
});

Select a state value with reselect:

const userDisplaySel = loginModule.selector(state => state.user).then(user => `${user.name} (${user.username})`);

store.subscribe(() => {
    const userDisplay = userDisplaySel(store.getState());
    console.log(userDisplay); // Foo (username)
});

7. Dispatch actions

// type: example.login.login
// payload:
//  username: 'username'
//  password: 'password'
store.dispatch(login('username', 'password'));

Using with React

import React from 'react';
import connect from 'react-redux';
import loginModule, { login } from './loginModule';

const mapStateToProps = state => {
    const loginState = loginModule.fromStore(state).getState();
    return {
        user: loginState.user
    }
};

const mapDispatchToProps = dispatch => ({
    login: (username, password) => dispatch(login(username, password))
});

const UserMenu = ({user, login}) => {
    return (
        <div>
            {/* display user and dispatch login action */}
        </div>
    );
};

UserMenu = connect(mapStateToProps, mapDispatchToProps)(UserMenu);

export default UserMenu;
1.0.0-beta.2

6 years ago

1.0.0-beta.1

6 years ago

1.0.0-alpha.7

6 years ago

1.0.0-alpha.6

6 years ago

1.0.0-alpha.5

6 years ago

1.0.0-alpha.4

6 years ago

1.0.0-alpha.3

6 years ago

1.0.0-alpha.2

6 years ago

1.0.0-alpha.1

6 years ago