1.0.6 • Published 6 years ago

redux-citrus v1.0.6

Weekly downloads
4
License
MIT
Repository
github
Last release
6 years ago

npm.io redux-citrus

License Build Status Version

Redux middleware to enable reusable redux components

Redux default reducers don't allow for easy re-usable redux components. Redux-Citrus provides a new combineReducer function citrusReducers that takes a reducer-configuration object and returns a rootReducer.

Usage

Let's say multiple modules in our state require similar functionality. Normally, actions and reducers are location agnostic. To re-use redux components we require additional information in our reducers to select the appropriate slice. Redux-citrus makes it easy to have actions and reducers that work on multiple slices of the state.

In the following we work with a simple action/reducer example

export const increment = (value = 1) => {
    return {
        type: counterActions.INCREMENT,
        value
    }
}

// async-action using redux-thunk
export const asyncIncrement = (value = 1, delay = 500) => {
    return (dispatch) => {
        setTimeout(() => {
            dispatch(increment(value))
        }, delay);
    }
}

const initialState: counterState = {
    counter: 0
}

const counterReducer: Reducer<counterState> = (state = initialState, action) => {
    switch(action.type) {
        case counterActions.INCREMENT: {
            return { counter: (state.counter)+action.value}
        }
        case counterActions.DECREMENT: {
            return {counter: (state.counter)-action.value}
        }
        default: {
            return state;
        }
    }
}

Furthermore, our state contains multiple modules that want to use the counter functionality

const reducers = {
    clickCounter: counterReducer,
    objectCounter: counterReducer
}

To create our rootReducer that can work on slices we use the citrusReducers function

import { citrusReducers } from 'redux-citrus';
const rootReducer = citrusReducers(reducers);

Citrus-Redux now provides our state a wrapper function to specify which slice we want to target with our actions

import { increment, asyncIncrement } from ...
const { clickCounter, objectCounter } = store.getState();

// works with normal actions
store.dispatch(clickCounter.withCitrus(increment(5)));
store.dispatch(clickCounter.withCitrus(increment()));
// and async-actions (using redux-thunk)
store.dispatch(objectCounter.withCitrus(asyncIncrement(100, 1000)));

This works, because citrusReducers always inject the withCitrus function that takes either an action or an async-action (redux-thunk) and wraps it in its own logic to handle the location. This is done by injecting an location property into actions.

For a running example check out src/index.tsx

Build

Clone this repository and run npm install. For the development build run npm run dev, it will create a development server listening on port 8080. For the minified production build run npm run build.

License

MIT - Copyright 2018 Florian Marienwald

1.0.6

6 years ago

1.0.5

6 years ago

1.0.4

6 years ago

1.0.3

6 years ago