Skip to content

Instantly share code, notes, and snippets.

@Dr-Nikson
Forked from vjpr/README.md
Last active January 14, 2019 06:35
Show Gist options
  • Select an option

  • Save Dr-Nikson/3c1b870f63dc0de67c38 to your computer and use it in GitHub Desktop.

Select an option

Save Dr-Nikson/3c1b870f63dc0de67c38 to your computer and use it in GitHub Desktop.

Revisions

  1. Dr-Nikson revised this gist Jul 1, 2015. 1 changed file with 4 additions and 11 deletions.
    15 changes: 4 additions & 11 deletions helpers.js
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,4 @@
    // redux-helpers.js

    import _ from 'lodash';
    import uniqueId from 'uniqueid';
    @@ -33,8 +34,8 @@ export const createActions = (actionObj) => {
    };
    }
    };
    if (actionObj._asyncActions[key]) {
    let [ begin, success, failure ] = asyncTypes;
    if (actionCreator._async === true) {
    const [ begin, success, failure ] = asyncTypes;
    method._id = {
    begin,
    success,
    @@ -80,15 +81,7 @@ export function promiseMiddleware() {

    export function asyncAction() {
    return (target, name, descriptor) => {
    if (!target._asyncActions) {
    Object.defineProperty(target, '_asyncActions', {
    value: {},
    enumerable: false,
    configurable: true,
    writable: true
    });
    }
    target._asyncActions[name] = name;
    descriptor.value._async = true;
    return descriptor;
    };
    }
  2. Dr-Nikson revised this gist Jun 30, 2015. 4 changed files with 103 additions and 8 deletions.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -2,4 +2,4 @@

    - Create actions similar to Flummox.
    - Generate action ids.
    - Supports actions with promises, and therefore ES7 async.
    - Supports actions with decorators, promises, and therefore ES7 async.
    10 changes: 4 additions & 6 deletions actions.js
    Original file line number Diff line number Diff line change
    @@ -2,7 +2,7 @@
    // 4 different ways to write actions: ES7 Async/Await, Promises, Async Function, Synchronous.
    //

    import {createActions} from './helpers.js'
    import {createActions, asyncAction} from './helpers.js'

    export const CounterActions = createActions({

    @@ -19,6 +19,8 @@ export const CounterActions = createActions({

    },

    // Use decorator to mark action that returns promise
    @asyncAction()
    incrementPromise() {

    // Debug
    @@ -28,11 +30,7 @@ export const CounterActions = createActions({
    }, 1000)
    })

    return {
    types: ['INCREMENT_BEGIN', 'INCREMENT_SUCCESS', 'INCREMENT_FAILURE'],
    promise,
    }

    return promise;
    },

    incrementFunctionWithState() {
    94 changes: 94 additions & 0 deletions helpers.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,94 @@

    import _ from 'lodash';
    import uniqueId from 'uniqueid';

    // Create actions that don't need constants :)
    export const createActions = (actionObj) => {
    const baseId = uniqueId();
    return _.zipObject(_.map(actionObj, (actionCreator, key) => {
    const actionId = `${baseId}-${key}`;
    const asyncTypes = ['BEGIN', 'SUCCESS', 'FAILURE'].map( (state) => `${actionId}-${state}`);
    const method = (...args) => {
    const result = actionCreator(...args);

    if (result instanceof Promise) {
    // Promise (async)
    return {
    types: asyncTypes,
    promise: result,
    };
    } else if (typeof result === 'function') {
    // Function (async)
    return (...args) => { // eslint-disable-line no-shadow
    return {
    type: actionId,
    ...(result(...args) || {})
    };
    };
    } else { // eslint-disable-line no-else-return
    // Object (sync)
    return {
    type: actionId,
    ...(result || {})
    };
    }
    };
    if (actionObj._asyncActions[key]) {
    let [ begin, success, failure ] = asyncTypes;
    method._id = {
    begin,
    success,
    failure
    };
    } else {
    method._id = actionId;
    }
    return [key, method];
    }));
    };

    // Get action ids from actions created with `createActions`
    export const getActionIds = (actionCreators) => {
    return _.mapValues(actionCreators, (value, key) => { // eslint-disable-line no-unused-vars
    return value._id;
    });
    };

    // Replace switch statements in stores (taken from the Redux README)
    export const createStore = (initialState, handlers) => {
    return (state = initialState, action = {}) =>
    handlers[action.type] ?
    handlers[action.type](state, action) :
    state;
    };

    export function promiseMiddleware() {
    return (next) => (action) => {
    const { promise, types, ...rest } = action;
    if (!promise) {
    return next(action);
    }

    const [REQUEST, SUCCESS, FAILURE] = types;
    next({ ...rest, type: REQUEST });
    return promise.then(
    (result) => next({ ...rest, result, type: SUCCESS }),
    (error) => next({ ...rest, error, type: FAILURE })
    );
    };
    }

    export function asyncAction() {
    return (target, name, descriptor) => {
    if (!target._asyncActions) {
    Object.defineProperty(target, '_asyncActions', {
    value: {},
    enumerable: false,
    configurable: true,
    writable: true
    });
    }
    target._asyncActions[name] = name;
    return descriptor;
    };
    }
    5 changes: 4 additions & 1 deletion store.js
    Original file line number Diff line number Diff line change
    @@ -8,7 +8,10 @@ const initialState = 0

    export const counter = createStore(initialState, {

    [actions.increment+'-SUCCESS']: (state, actions) => {
    // actions.incrementPromise.begin
    // actions.incrementPromise.success
    // actions.incrementPromise.failure
    [actions.incrementPromise.success]: (state, actions) => {
    return state + 5
    },

  3. @vjpr vjpr revised this gist Jun 19, 2015. 1 changed file with 0 additions and 4 deletions.
    4 changes: 0 additions & 4 deletions app.js
    Original file line number Diff line number Diff line change
    @@ -2,10 +2,6 @@ import React from 'react';
    import {Provider} from 'redux/react';
    import {RouteHandler} from 'react-router'

    ////////////////////////////////////////////////////////////////////////////////
    // Redux
    ////////////////////////////////////////////////////////////////////////////////

    import {createRedux, createDispatcher, composeStores} from 'redux';
    import thunkMiddleware from 'redux/lib/middleware/thunk';
    import {compose} from 'redux';
  4. @vjpr vjpr revised this gist Jun 19, 2015. 1 changed file with 4 additions and 3 deletions.
    7 changes: 4 additions & 3 deletions index.js
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,4 @@
    React.render(<App/>
    , document.getElementById('body')
    )
    import React from 'react'
    import App from './app.js'

    React.render(<App/>, document.getElementById('body'))
  5. @vjpr vjpr revised this gist Jun 19, 2015. 1 changed file with 3 additions and 0 deletions.
    3 changes: 3 additions & 0 deletions index.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,3 @@
    React.render(<App/>
    , document.getElementById('body')
    )
  6. @vjpr vjpr revised this gist Jun 19, 2015. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions actions.js
    Original file line number Diff line number Diff line change
    @@ -35,7 +35,7 @@ export const CounterActions = createActions({

    },

    incrementFunction() {
    incrementFunctionWithState() {
    return (dispatch, getState) => {
    const {counter} = getState()
    console.log(dispatch)
    @@ -44,7 +44,7 @@ export const CounterActions = createActions({
    }
    },

    incrementAnotherAction()) {
    incrementFunction()) {
    return dispatch => {
    setTimeout(() => {
    dispatch(CounterActions.increment())
  7. @vjpr vjpr revised this gist Jun 19, 2015. 1 changed file with 5 additions and 1 deletion.
    6 changes: 5 additions & 1 deletion actions.js
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,7 @@
    //
    // 4 different ways to write actions: ES7 Async/Await, Promises, Async Function, Synchronous.
    //

    import {createActions} from './helpers.js'

    export const CounterActions = createActions({
    @@ -48,7 +52,7 @@ export const CounterActions = createActions({
    }
    },

    decrement() {
    increment() {
    return {}
    },

  8. @vjpr vjpr revised this gist Jun 19, 2015. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,5 @@
    # Reduce boilerplate in Redux

    - Create actions similar to Flummox.
    - Generate action ids.
    - Supports actions with promises, and therefore ES7 async.
  9. @vjpr vjpr renamed this gist Jun 19, 2015. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  10. @vjpr vjpr revised this gist Jun 19, 2015. 3 changed files with 34 additions and 130 deletions.
    61 changes: 28 additions & 33 deletions actions.js
    Original file line number Diff line number Diff line change
    @@ -1,14 +1,9 @@
    import {createActions} from 'redux-helpers'
    import {createActions} from './helpers.js'

    export const CounterActions = createActions({

    increment() {
    return {}
    },
    async incrementAsync() {

    async incrementIfOdd() {

    // Debug
    const promise = new Promise((resolve, reject) => {
    setTimeout(() => {
    resolve()
    @@ -20,32 +15,32 @@ export const CounterActions = createActions({

    },

    //incrementIfOdd() {
    //
    // // Debug
    // const promise = new Promise( (resolve, reject) => {
    // setTimeout(() => {
    // resolve()
    // }, 1000)
    // })
    //
    // return {
    // types: ['INCREMENT_BEGIN', 'INCREMENT_SUCCESS', 'INCREMENT_FAILURE'],
    // promise,
    // }
    //
    //},

    //incrementIfOdd() {
    // return (dispatch, getState) => {
    // const {counter} = getState()
    // console.log(dispatch)
    // if (counter % 2 === 0) return
    // dispatch(CounterActions.increment())
    // }
    //},

    incrementAsync() {
    incrementPromise() {

    // Debug
    const promise = new Promise( (resolve, reject) => {
    setTimeout(() => {
    resolve()
    }, 1000)
    })

    return {
    types: ['INCREMENT_BEGIN', 'INCREMENT_SUCCESS', 'INCREMENT_FAILURE'],
    promise,
    }

    },

    incrementFunction() {
    return (dispatch, getState) => {
    const {counter} = getState()
    console.log(dispatch)
    if (counter % 2 === 0) return
    dispatch(CounterActions.increment())
    }
    },

    incrementAnotherAction()) {
    return dispatch => {
    setTimeout(() => {
    dispatch(CounterActions.increment())
    84 changes: 3 additions & 81 deletions gistfile1.md
    Original file line number Diff line number Diff line change
    @@ -1,82 +1,4 @@
    Redux is super lightweight...so it may be useful to add some helper utils on top of it to reduce some boilerplate. The goal of Redux is to keep these things in user-land, and so most likely these helpers (or anything like them) wouldn't make it into core.
    # Reduce boilerplate in Redux

    It's important to note that this is just ONE (and not particularly thoroughly tested) way to accomplish the goal of reducing boilerplate in Redux. It borrows some ideas from Flummox and the way it generates action creator constants.

    This will evolve, I'm sure, as time goes on and as Redux's API changes.

    Some helper functions to reduce some boilerplate in Redux:

    ```javascript
    import _ from 'lodash';
    import uniqueId from 'uniqueid';

    // Create actions that don't need constants :)
    export const createActions = (actionObj) => {
    const baseId = uniqueId();
    return _.zipObject(_.map(actionObj, (actionCreator, key) => {
    const actionId = `${baseId}-${key}`;
    const method = (...args) => {
    const result = actionCreator(...args);
    return {
    type: actionId,
    ...(result || {})
    };
    };
    method._id = actionId;
    return [key, method];
    }));
    };

    // Get action ids from actions created with `createActions`
    export const getActionIds = (actionCreators) => {
    return _.mapValues(actionCreators, (value, key) => {
    return value._id;
    });
    };

    // Replace switch statements in stores (taken from the Redux README)
    export const createStore = (initialState, handlers) => {
    return (state = initialState, action) =>
    handlers[action.type] ?
    handlers[action.type](state, action) :
    state;
    };
    ```

    They can be used like this:

    ### Actions

    ```javascript
    import {createActions} from 'lib/utils/redux';

    export const SocialPostActions = createActions({
    loadPosts(posts) {
    return { posts };
    }
    });
    ```

    ### Stores

    ```javascript
    import {default as Immutable, Map, List} from 'immutable';
    import {createStore, getActionIds} from 'lib/utils/redux';

    import {SocialPostActions} from 'lib/actions';

    const initialState = Map({
    isLoaded: false,
    posts: List()
    });

    const actions = getActionIds(SocialPostActions);

    export const posts = createStore(initialState, {
    [actions.loadPosts]: (state, action) => {
    return state.withMutations(s =>
    s.set('isLoaded', true).set('posts', Immutable.fromJS(action.posts))
    );
    }
    });
    ```
    - Generate action ids.
    - Supports actions with promises, and therefore ES7 async.
    19 changes: 3 additions & 16 deletions store.js
    Original file line number Diff line number Diff line change
    @@ -1,28 +1,15 @@
    import {createStore, getActionIds} from 'redux-helpers'
    import {createStore, getActionIds} from './helpers.js'
    import {default as Immutable, Map, List} from 'immutable'

    import {CounterActions} from '../actions'
    import {CounterActions} from './actions.js'

    const actions = getActionIds(CounterActions)

    const initialState = 0

    export const counter = createStore(initialState, {

    [actions.incrementIfOdd+'-SUCCESS']: (state, actions) => {
    [actions.increment+'-SUCCESS']: (state, actions) => {
    return state + 5
    },

    ['INCREMENT_SUCCESS']: (state, actions) => {
    return state + 3
    },

    [actions.increment]: (state, actions) => {
    return state + 1
    },

    [actions.decrement]: (state, actions) => {
    return state - 1
    },

    })
  11. @vjpr vjpr revised this gist Jun 19, 2015. 3 changed files with 131 additions and 0 deletions.
    60 changes: 60 additions & 0 deletions actions.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,60 @@
    import {createActions} from 'redux-helpers'

    export const CounterActions = createActions({

    increment() {
    return {}
    },

    async incrementIfOdd() {

    // Debug
    const promise = new Promise((resolve, reject) => {
    setTimeout(() => {
    resolve()
    }, 1000)
    })

    let result = await promise
    return result

    },

    //incrementIfOdd() {
    //
    // // Debug
    // const promise = new Promise( (resolve, reject) => {
    // setTimeout(() => {
    // resolve()
    // }, 1000)
    // })
    //
    // return {
    // types: ['INCREMENT_BEGIN', 'INCREMENT_SUCCESS', 'INCREMENT_FAILURE'],
    // promise,
    // }
    //
    //},

    //incrementIfOdd() {
    // return (dispatch, getState) => {
    // const {counter} = getState()
    // console.log(dispatch)
    // if (counter % 2 === 0) return
    // dispatch(CounterActions.increment())
    // }
    //},

    incrementAsync() {
    return dispatch => {
    setTimeout(() => {
    dispatch(CounterActions.increment())
    }, 1000)
    }
    },

    decrement() {
    return {}
    },

    })
    43 changes: 43 additions & 0 deletions app.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,43 @@
    import React from 'react';
    import {Provider} from 'redux/react';
    import {RouteHandler} from 'react-router'

    ////////////////////////////////////////////////////////////////////////////////
    // Redux
    ////////////////////////////////////////////////////////////////////////////////

    import {createRedux, createDispatcher, composeStores} from 'redux';
    import thunkMiddleware from 'redux/lib/middleware/thunk';
    import {compose} from 'redux';
    import {promiseMiddleware} from './helpers.js';
    import * as stores from './store.js';

    const store = composeStores(stores);

    const dispatcher = createDispatcher(
    store,
    getState => [promiseMiddleware(), thunkMiddleware(getState)]
    );

    const redux = createRedux(dispatcher);

    ////////////////////////////////////////////////////////////////////////////////

    // We use the above code - which this is shorthand for this, but adds our promise middleware.
    //const redux = createRedux(stores)

    ////////////////////////////////////////////////////////////////////////////////

    export default class App extends React.Component {

    render() {
    return (
    <Provider redux={redux}>
    {() =>
    <RouteHandler/>
    }
    </Provider>
    );
    }

    }
    28 changes: 28 additions & 0 deletions store.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,28 @@
    import {createStore, getActionIds} from 'redux-helpers'
    import {default as Immutable, Map, List} from 'immutable'

    import {CounterActions} from '../actions'

    const actions = getActionIds(CounterActions)

    const initialState = 0

    export const counter = createStore(initialState, {

    [actions.incrementIfOdd+'-SUCCESS']: (state, actions) => {
    return state + 5
    },

    ['INCREMENT_SUCCESS']: (state, actions) => {
    return state + 3
    },

    [actions.increment]: (state, actions) => {
    return state + 1
    },

    [actions.decrement]: (state, actions) => {
    return state - 1
    },

    })
  12. @skevy skevy revised this gist Jun 16, 2015. No changes.
  13. @skevy skevy revised this gist Jun 16, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion gistfile1.md
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,6 @@
    Redux is super lightweight...so it may be useful to add some helper utils on top of it to reduce some boilerplate. The goal of Redux is to keep these things in user-land, and so most likely these helpers (or anything like them) wouldn't make it into core.

    It's important to note that this is just ONE (and not particularly thoroughly tested) way to accomplish the goal of reducing boilerplate in Redux.
    It's important to note that this is just ONE (and not particularly thoroughly tested) way to accomplish the goal of reducing boilerplate in Redux. It borrows some ideas from Flummox and the way it generates action creator constants.

    This will evolve, I'm sure, as time goes on and as Redux's API changes.

  14. @skevy skevy revised this gist Jun 16, 2015. No changes.
  15. @skevy skevy revised this gist Jun 16, 2015. 1 changed file with 16 additions and 13 deletions.
    29 changes: 16 additions & 13 deletions gistfile1.md
    Original file line number Diff line number Diff line change
    @@ -10,19 +10,7 @@ Some helper functions to reduce some boilerplate in Redux:
    import _ from 'lodash';
    import uniqueId from 'uniqueid';

    export const getActionIds = (actionCreators) => {
    return _.mapValues(actionCreators, (value, key) => {
    return value._id;
    });
    };

    export const createStore = (initialState, handlers) => {
    return (state = initialState, action) =>
    handlers[action.type] ?
    handlers[action.type](state, action) :
    state;
    };

    // Create actions that don't need constants :)
    export const createActions = (actionObj) => {
    const baseId = uniqueId();
    return _.zipObject(_.map(actionObj, (actionCreator, key) => {
    @@ -38,6 +26,21 @@ export const createActions = (actionObj) => {
    return [key, method];
    }));
    };

    // Get action ids from actions created with `createActions`
    export const getActionIds = (actionCreators) => {
    return _.mapValues(actionCreators, (value, key) => {
    return value._id;
    });
    };

    // Replace switch statements in stores (taken from the Redux README)
    export const createStore = (initialState, handlers) => {
    return (state = initialState, action) =>
    handlers[action.type] ?
    handlers[action.type](state, action) :
    state;
    };
    ```

    They can be used like this:
  16. @skevy skevy renamed this gist Jun 16, 2015. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  17. @skevy skevy created this gist Jun 16, 2015.
    79 changes: 79 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,79 @@
    Redux is super lightweight...so it may be useful to add some helper utils on top of it to reduce some boilerplate. The goal of Redux is to keep these things in user-land, and so most likely these helpers (or anything like them) wouldn't make it into core.

    It's important to note that this is just ONE (and not particularly thoroughly tested) way to accomplish the goal of reducing boilerplate in Redux.

    This will evolve, I'm sure, as time goes on and as Redux's API changes.

    Some helper functions to reduce some boilerplate in Redux:

    ```javascript
    import _ from 'lodash';
    import uniqueId from 'uniqueid';

    export const getActionIds = (actionCreators) => {
    return _.mapValues(actionCreators, (value, key) => {
    return value._id;
    });
    };

    export const createStore = (initialState, handlers) => {
    return (state = initialState, action) =>
    handlers[action.type] ?
    handlers[action.type](state, action) :
    state;
    };

    export const createActions = (actionObj) => {
    const baseId = uniqueId();
    return _.zipObject(_.map(actionObj, (actionCreator, key) => {
    const actionId = `${baseId}-${key}`;
    const method = (...args) => {
    const result = actionCreator(...args);
    return {
    type: actionId,
    ...(result || {})
    };
    };
    method._id = actionId;
    return [key, method];
    }));
    };
    ```

    They can be used like this:

    ### Actions

    ```javascript
    import {createActions} from 'lib/utils/redux';

    export const SocialPostActions = createActions({
    loadPosts(posts) {
    return { posts };
    }
    });
    ```

    ### Stores

    ```javascript
    import {default as Immutable, Map, List} from 'immutable';
    import {createStore, getActionIds} from 'lib/utils/redux';

    import {SocialPostActions} from 'lib/actions';

    const initialState = Map({
    isLoaded: false,
    posts: List()
    });

    const actions = getActionIds(SocialPostActions);

    export const posts = createStore(initialState, {
    [actions.loadPosts]: (state, action) => {
    return state.withMutations(s =>
    s.set('isLoaded', true).set('posts', Immutable.fromJS(action.posts))
    );
    }
    });
    ```