-
-
Notifications
You must be signed in to change notification settings - Fork 51
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
Function denormalize
throws RangeError: Maximum call stack size exceeded
- support selecting normalized objects by id
#331
Comments
I probably know what this is... see #317 Probably you have very many items in data, as well as very nested data for this query. Above issue would solve it. This could be also a different problem, but I cannot help without seeing data. |
Here is my data, I will continue debugging but if you see something that strikes your eyes. It might be that I'm trying to get the normalized data directly from the normalizedData dict... I still haven't figured out a way to get the normalized objects out of there ;) |
@zeraien do you mean that you are reading normalizedData from requestsReducer on your own? this is internal implementation detail and should not be read manually getQuery denormalizes data automatically, you don't need to think about it |
Well, sometimes I just need to obtain objects by ID from the cache, because it's not always that objects are in a request, maybe you just need a related object in a different context, but now of course I realize that it's not a good idea because the data in the normalizedData is normalized! I'll do some more digging and see if I can figure it out, it may very well not be an issue with your code, but with mine (most likely) hehe. |
I'm starting to think there might be something weird going on with the Here is what As you can see it's repeating. I will do more digging. |
Ok, so I found the cause. It's a recursion bug alright {
"id": "zVid0ty",
"date": "2019-12-27",
"barcode": "49394dcd-cd1b-46e8-82a2-2544c828d199",
"identifier": "rdT6T9uz",
"activities": [{
"id": "A1ibDFG2"
}, {
"id": "40i9vHdK"
}],
"parcels": [{
"id": "xwiA3sO",
"activities": [{
"id": "A1ibDFG2"
}, {
"id": "40i9vHdK"
}]
}]
} If I remove the This works: {
"id": "zVid0ty",
"date": "2019-12-27",
"barcode": "49394dcd-cd1b-46e8-82a2-2544c828d199",
"identifier": "rdT6T9uz",
"activities": [{
"id": "A1ibDFG2"
}, {
"id": "40i9vHdK"
}],
"parcels": [{
"id": "xwiA3sO",
"activities": null
}]
} |
Finally I narrowed down that the following The {
'@@xwiA3sO': {
id: 'xwiA3sO',
type: 'parcel',
activities: [
'@@A1ibDFG2',
'@@40i9vHdK'
],
},
'@@zVid0ty': {
id: 'zVid0ty',
type: 'consignment',
activities: [
'@@A1ibDFG2',
'@@40i9vHdK'
],
parcels: [
'@@xwiA3sO'
],
},
'@@40i9vHdK': {
id: '40i9vHdK',
type: 'activity',
parcels: [
'@@xwiA3sO'
],
},
'@@A1ibDFG2': {
id: 'A1ibDFG2',
type: 'activity',
parcels: [
'@@xwiA3sO'
],
}
} |
And now I realise that I guess that data structure simply won't work since it will indeed be infinitely recursive... my stupid. |
@zeraien if getQuery works then everything is fine What you try to do is symptom we need new feature -> get object by id, the problem is that we need usedKeys etc which you can inspect in requestsReducer, it is possible some stuff will need to be refactored. For now I hope you will solve it on the app level, but I will add this to TODO list so this will be built-in. |
@zeraien I thought about it and there is 1 issue. {
id: 1,
name: 'name',
bestFriend: {
id: 2,
name: 'name 2',
bestFriend: {
id: 1,
name: 'name',
}
}
}
} As you can see denormalizing would indeed cause endless loop. For queries it is not a problem thanks to So based on the example information that nested user has only Now we want to allow to get an orbitrary object. For this case we dont have Do you have any idea how we could solve that? |
Also, the question is why do you even need to do that? Perhaps what you need is just action.meta.requestKey, so that you could have more queries of the same type stored inside reducer, like with multiple different ids. |
Good point, so it can indeed become an issue! {
id: 2,
name: 'friend 2',
bestFriend: () => get("@@1") -> {id:1, name:'friend 1', bestFriend: get()}
},
{
id: 1,
name: 'friend 1',
bestFriend: () => get("@@2")
} But that brings with it other complications, in theory, whoever has to work with that data structure risks going into an infinite loop themselves... Another alternative is to simply cut the feed at level 2.
I guess you can check if the parent has the same key and then simply not include that key. But that risks mangling someone's data, although you could mitigate with a console warning... Alternatively, simply find a way to detect the infinite loop and warn the user so they can change the API... |
Relations has to be stored as strings, this has to be serializable. Introducing a warning is 1 idea, but in our example API really is just fine, it just has recursive relationship but for queries with Another idea is to limit nesting depth, but like you said this would mangling data. I think about catching this error indeed and showing a message like So actually app user would provide proper usedKeys for a give object oneself. I cannot see any other way. But the most important question is, why do you even need this? Please provide use case, maybe I will give you another way to achieve what you need. |
I don't really need it, it was just my API was configured in this way and so I changed my API to compensate. |
@zeraien usedKeys would be provided to new selector like normally this selector would just get id and it would return proper object, but if leading to recursive error, this would be catched and warning would be shown in console. then someone could do thing like: const myObject = getNormalizedObjectById(state, { id: '1', usedKeys: {
id: true,
name: true,
bestFriend: {
id: true,
name: true,
}
}}}); So usedKeys would be provided in easy to work with way by human, while library would convert it to the same structure as stored in reducer. Probably this would be used very sparingly, only when recursive relationship, but we would have an escape hatch so I could work on |
actually this could be represented as graphql query, like: {
id
name
bestFriend {
id
name
}
} in theory such parsing could be also allowed via graphql driver |
if I think about it more, this looks like graphql fragment concept, but for any api, including REST |
denormalize
throws RangeError: Maximum call stack size exceeded
denormalize
throws RangeError: Maximum call stack size exceeded
- support selecting normalized objects by id
I still haven't been able to figure out how or why, but sometimes the function
denormalize
innormalizers/denormalize.js
, will go into an infinite recursion loop while loading data.Not sure where to start debugging it...
The trace starts in getQuerySelector, so I'm trying to use that to obtain the result of a normalized request.
The text was updated successfully, but these errors were encountered: