-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Differentiate results #22
Comments
Something like the following could be implemented as well to make the state more flexible: options:
methodReducer.jsimport { 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),
}),
{}
)
); Usageimport 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 }
}
*/ |
Just want to let you know I'm still thinking about it. |
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. |
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.
|
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. |
@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! |
@hauckwill Glad you got it working, it's not the most elegant solution but it works for now. |
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:
I need to
find
a list of data sets based on different query options.If I wanted to display two lists of data sets on the same page I would need to have two reducers right now in order to distinguish the results and to prevent them from being overwritten.
I
get
a data set from the server. I have an error message field which should print a warning if the data could not be fetched.When the data was successfully fetched from the server I want to change it somehow. So I do an
update
. If theupdate
failed and I now go back to my preview of the data I get an error message which I can't tell if it was from theget
or theupdate
, so I have to add additional state to distinguish.I
find
an array of data sets from my server which give me basic information about my entries. I now want toget
each entry of the same endpoint afterwards and load them into my view so that my application doesn't hang and the user wouldn't need to wait until all of the data was fetched before he could interact with the UI. How should I get both the result of thefind
and all results ofget
into the state?So here are some possible solutions:
You could set something like a 'namespace' in the action to let the reducer know in which substate the result should be put. This would give the user most control about the data but would cause a lot of substates which may never be reused afterwards. I also don't think that this would be redux conform as you would modify the way the reducer works in the actions which should be prevented if possible.
A mechanism to inject the result into queryResult?
Please let me know what you think about this.
The text was updated successfully, but these errors were encountered: