feathersjs-ecosystem / feathers-redux

Integrate Feathers with your Redux store
MIT License
114 stars 23 forks source link

Differentiate results #22

Open 2manyvcos opened 7 years ago

2manyvcos commented 7 years ago

I like the approach of this package and the simplicity on how it works.

Edit I tested a lot and simplified this issue based on my tests:

Please look at following situations to understand my issue:

So here are some possible solutions:

Please let me know what you think about this.

2manyvcos commented 7 years ago

Something like the following could be implemented as well to make the state more flexible:

options:

{
  ...,
  shape: ..., // <-- the mapping - if undefined, the current reducer should be returned directly
}
methodReducer.js ```js import { combineReducers } from 'redux'; import _ from 'lodash'; const childReducer = (reducer, keywords, initState = {}) => (state = initState, action = {}) => (_.isString(action.type) && keywords.find((keyword) => action.type.indexOf(keyword) !== -1)) ? reducer(state, action) : state; const stringSafe = (value) => _.isString(value) ? [value] : value; const normalizeMappingValue = (value) => { const sValue = stringSafe(value); if (_.isArray(sValue)) return normalizeMappingValue({ keywords: sValue }); if (_.isObject(sValue)) { const { keywords, ...rest } = sValue; const sKeywords = stringSafe(keywords); return { ...rest, keywords: sKeywords.map((keyword) => `_${keyword.toUpperCase()}`), }; } return { keywords: [] }; }; const normalizeMapping = (mapping) => { const sMapping = stringSafe(mapping); if (_.isArray(sMapping)) { return normalizeMapping(_.reduce( sMapping, (sum, val) => ({ ...sum, [val]: val }), {} )); } if (_.isObject(sMapping)) { return _.reduce( sMapping, (sum, value, key) => ({ ...sum, [key]: normalizeMappingValue(value), }), {} ); } return {}; }; export default (reducer, mapping) => !mapping ? reducer : combineReducers( _.reduce( normalizeMapping(mapping), (sum, { keywords, initState }, key) => ({ ...sum, [key]: childReducer(reducer, keywords, initState), }), {} ) ); ```
Usage ```js import methodReducer from '...'; const likeNowReducer = methodReducer(services.myService.reducer); // same as return services.myService.reducer const verySimpleReducer = methodReducer(services.myService.reducer, 'find'); // maps only find /* { find: { ...results of find } } */ const simpleReducer = methodReducer(services.myService.reducer, ['find', 'get', 'create', 'update', 'patch', 'delete']); // maps all methods into different substates /* { find: { ...results of find }, get: { ...results of get }, create: { ...results of create }, update: { ...results of update }, patch: { ...results of patch }, delete: { ...results of delete } } */ const advancedReducer = methodReducer(services.myService.reducer, { find: 'find', get: 'get', put: 'create', alter: [ 'update', 'patch' ], delete: 'delete' }); // maps find, get and delete normally but maps create to put and combines update and patch to one substate named alter /* { find: { ...results of find }, get: { ...results of get }, put: { ...results of create }, alter: { ...results of update and patch }, delete: { ...results of delete } } */ ```
eddyystop commented 7 years ago

Just want to let you know I'm still thinking about it.

eddyystop commented 7 years ago

Related is https://github.com/feathersjs/feathers-redux/issues/35 Related https://github.com/feathersjs/feathers-redux/issues/24

plhosk commented 7 years ago

I ran into this issue while building a basic redux + feathers application. For now I'm using the base feathers client combined with redux and redux-saga.

Sicria commented 7 years ago

Any update on this? The base functionality is great, but Situation A is really common.

Edit - Ended up using the following, seem to provide the functionality I was after.

export function feathersReduxServices(app) {
  return {
    ...reduxifyServices(app, [
      'users',
      'articles',
    ]),
    ...reduxifyServices(app, { articles: 'topArticles' }),
  };
}
eddyystop commented 7 years ago

I'm tied up with a lot of feathers development, and documentation for the new version right now.

Changes to feathers-redux are on the road-map, including an optional immutable store, but I won't realistically get to it before Jan 2018.

greyivy commented 6 years ago

@Sicria Using this and the state is not being modified correctly... Are you sure this is working?

I'm using the same set-up that you are, but when I dispatch a find on 'articles', both 'articles' and 'topArticles' are modified.

Dispatching find on 'topArticles' causes neither of them to be modified, but I'm able to access the result from the promise.

Has anyone found a solution?

Edit: Never mind: I had my reducers set up incorrectly. Thanks for the solution!

Sicria commented 6 years ago

@hauckwill Glad you got it working, it's not the most elegant solution but it works for now.