Coder Social home page Coder Social logo

adrienjt / redux-data-structures Goto Github PK

View Code? Open in Web Editor NEW
158.0 5.0 4.0 45 KB

Reducer factory functions for common data structures: counters, maps, lists (queues, stacks), sets, etc.

Home Page: https://redux-data-structures.js.org

License: MIT License

JavaScript 82.18% HTML 17.82%
redux reducer-makers common-reducers counter toggle map queue stack dictionary set

redux-data-structures's People

Contributors

adrienjt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

redux-data-structures's Issues

Import as Module

screen shot 2017-07-27 at 6 50 09 pm

Looks like when importing as a module src/ is used and there is possibly some type of babel transformation plugin being used that I don't have in my project.

TypeScript?

Do you plan supporting it (@types/redux-data-structures), rewrite the library on TS or accepting a pull request that refactors it on TS?

Issue Building With Create React App

When using redux-data-structures in a Create React App based system development works fine. However when creating a production build using yarn build an UglifyJS error pops up:

screen shot 2017-08-08 at 10 06 38 am

Looks like an issue with Uglification on the defaults set inside the function definitions.

Interestingly cloning the redux-data-structures repository into a sub-directory of src in the app, building it, and linking directly to es6/index.js works just fine for both development and production build.

Feature: "add all" action types for maps

Right now there is no simple way to add multiple items at once to a map. We have to dispatch an add action for each element when we want to add a list of items.

It would be nice to have a addAllActionTypes option that would iterate on the action's payload and add all items. This could also need a collectionGetter option.

For lists, since you're using Array.prototype.concat, the add actions work for adding both single and multiple items.

Help request: Map implementation

I am trying to implement set serialization, and have checkout out yours, though did not understand it.
How does it work ?
My aim is to have one of my reducers populate and read stateful Map in Redux Store, how would I do that ?

const reducer = (state = {
  statefulMap: new Map()
}, action) => {
switch
    case: {
      let newMap = new Map(state.statefulMap)
      action.newObjects.forEach(newMap.set(`${p.id},${p.search_keyword}`, 
      return Object.
return {
          statefulMap: newMap
        }
    }

Thanks for any thoughts.

Example of Simple Value Map

A pattern I often find myself using, particularly for things like user data or the like, is a simple key: value map. In this instance the map() only really adds additional boilerplate while dealing with ids and such. After some tinkering I came up with a simple enough solution leveraging the existing value() data structure. While nothing amazingly original I thought maybe adding an example to the readme/docs for this use case could be useful. Example:

import { combineReducers, createStore } from 'redux';
import { value } from 'redux-data-structures';

const name = value({
  setActionsTypes: ['UPDATE_NAME']
});

const email = value({
  setActionsTypes: ['UPDATE_EMAIL']
});

const reducers = combineReducers({
  user: {
    name,
    email
  }
})

const store = createStore(reducers);

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

store.dispatch({ type: 'UPDATE_NAME', payload: 'FirstName LastName' });
// {
//   "user": {
//     "name": "FirstName LastName",
//     "email": null
//   }
// }
store.dispatch({ type: 'UPDATE_EMAIL', payload: '[email protected]' });
// {
//   "user": {
//     "name": "FirstName LastName",
//     "email": "[email protected]"
//   }
// }

Feature: make getters generator functions

What about an idea to make getter methods be a generator function? It can allow us to do this for example:

const todos = map({
  addActionTypes: ['ADD_FEW_TODOS'],
  *keyGetter(action) {
    yield* action.payload.map(todo => todo.id);
  },
  *itemGetter(action) {
    yield* action.payload;
  },
});

I think it is an easy way to solve the problem described here #5 (comment)

Put getters together with action types

If I have two action types with different payload structure I have to describe the types and functions for selecting the data from these action in different places

const todos = map({
  addActionTypes: ['ADD_TODO', 'ADD_NOTE_WITH_TODO'],
  keyGetter: action => {
    if (action.type === 'ADD_NOTE_WITH_TODO') {
      return action.payload.note.todo.id;
    }

    if (action.type === 'ADD_TODO') {
      return action.payload.id;
    }
  },
  itemGetter: action => {
    if (action.type === 'ADD_NOTE_WITH_TODO') {
      return action.payload.note.todo;
    }

    if (action.type === 'ADD_TODO') {
      return action.payload;
    }
  },
});

That looks pretty bad because we divide describing action type and related logic.

What about describing all related getter methods together with these types?

const todos = map({
  addActionTypes: [
    { 
      type: 'ADD_TODO' 
    },
    {
      type: 'ADD_NOTE_WITH_TODO',
      keyGetter: action => action.payload.note.todo.id,
      itemGetter: action => action.payload.note.todo,
    },
  ],
});

Food for thought

Hey guys,
I noticed this mentioned in a react newsletter and it looks similar to an approach I took with moving our app to redux.

Couple of things I didn't like about the default redux code found in tutorials:

  • loads of uniquely named actions (ADD_TODO) as opposed to namespacing (.ADD)
  • non-reuse of reducers and constantly creating more of them

I came up with following solution:

  • reducer factories (this is what you're doing)
  • utilizing namespace and the same action names across same reducers, jus twith a different namespace (this is what redux already offers, but I don't see it used often enough)
  • reducer factories create action trees (this is the food for thought)

Let me give you an example, with a singleton reducer (it just holds a value):

export default ((namespace, initial = null) => {
  const initialState = initial;
  var namespace;

  const handler = (state = initialState, action) => {
    const [action_namespace, action_type] = action.type.split('/');

    if (namespace != action_namespace) {
      return state;
    }

    switch (action_type) {
      case 'set':
        return action.payload;
      default:
        return state;
    }
  };

  let store;
  handler.__init = (_store, _namespace) => {
    store = _store;
    namespace = _namespace;
  };

  handler.__actions = {
    'set': (value) => {
      store.dispatch({
        type: namespace+'/set',
        payload: value
      });
    }
  };

  return handler;
});

Then I create the store like this:

import {
  createStore,
  combineReducers,
} from 'redux';

import {each} from 'lodash-es';
import {pluralize, camelize} from 'inflection';

import singletonReducer from '../reducers/singletonReducer';
import mapActions from './mapActions';


// This allows us to easily call actions on reducers, like so:
// Actions.task.set() and
const mapActions = (map, store, actions) => {

  // set actions for each store
  each(map, (v, k) => {
    if (v.__init) {
      v.__init(store, k);
      actions[k] = v.__actions;
    }
  });
};


const configureStore = (map, initialState = {}, actions = {}) => {
  const reducer = combineReducers(map);

  // pre-fill computer values
  initialState = wrappedReducer(initialState, {type: 'initComputed'});

  const store = createStore(
    reducer,
    initialState,
    window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
  );
  mapActions(map, store, actions);

  return store;
}

export default ({
  actions = {},
  state = window.__REDUX_INIT_CONTEXT,
} = {}) => {
  const map = {
    currentProjectId: singletonReducer(),
  };

  const store = configureStore(
    map,
    state,
    actions,
    globalReducers
  );

  return {
    redux: store,
    store: new Store(store, actions),
    actions: actions,
  };
};

Then I expose actions as window.Actions.

When I do that, I have a globally available map of actions, that is constructed by the reducers that I setup, so there is zero config, no need to remember or lookup action names.

Its all under Actions.<reducer>.<action>(...) and you can call it to dispatch action like that.

This is what I came up with in the first weeks and its super easy to use. You have far more experience so I bet you'll be able to come up with something smarter and cleaner if it inspires you.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.