Nested proxy-memoized selectors
drop-evan opened this issue · comments
Hi, I have a project where some of my proxy-memoized selectors are composed of other proxy-memoized selectors. I noticed that touches are not being recorded from the nested selectors, most likely because the proxy is being unwrapped and replaced with a new proxy within the nested selectors.
Is my understanding correct?
Is there a workaround you would suggest?
I could use the un-memoized versions to compose the higher order selectors but I would like to not have to manage two versions of each selector.
Hi, thanks for opening this up.
I had such use cases with nested selectors in mind.
https://github.com/dai-shi/proxy-memoize/blob/main/__tests__/20_nested_spec.ts should cover some use cases.
Could you create a test case, or a small reproduction in codesandbox?
I'm having trouble with codesandbox for some reason but I ran this in node and it seems to reproduce the issue
const memoize = require('proxy-memoize')
// comment the above import and replace memoize with the identity function and the code works as expected
// const memoize = fn => fn
const state1 = {
ids: [2, 3],
keyMap: {
1: 'k-1',
2: 'k-2',
3: 'k-3',
},
entities: {},
}
const state2 = {
ids: state1.ids,
keyMap: state1.keyMap,
entities: {
'k-1': 'e-1',
'k-2': 'e-2',
'k-3': 'e-3',
},
}
const getKeyById = memoize(({ state, id }) => {
return state.keyMap[id]
})
const getEntityById = memoize(({ state, id }) => {
return state.entities[getKeyById({ state, id })]
})
const getCurrentEntities = memoize(state => {
return state.ids.map(id => getEntityById({ state, id }))
})
console.log(getCurrentEntities(state1))
console.log(getCurrentEntities(state2))
It's a bit contrived but I'm trying to simulate the level of nesting we have with the selectors. I'm more concerned about why it's happening incase there are certain patterns of usage to avoid with proxy-memoize.
I'm having trouble with codesandbox for some reason
Is it about importing the library?
Yeah, I noticed that too.
Can you try this?
import memoize from "proxy-memoize/dist/index.modern.js";
It's a bit contrived
contrived one is fine. I wonder if we can make it a little smaller to reveal the issue.
my gut feeling is the shared keyMap
is causing something. 🤔
I'm having trouble with codesandbox for some reason
Is it about importing the library?
Yeah, I noticed that too. Can you try this?
import memoize from "proxy-memoize/dist/index.modern.js";
Yep that was it, thanks for the tip
https://codesandbox.io/s/prod-cookies-g9c4hd?file=/src/index.js
my gut feeling is the shared keyMap is causing something.
🤔
I shared some keys between state to simulate what might happen in a redux store, but even without doing that the issue seems to happen 🤔
I was able to simplify the sandbox example and reduce it to 1 level of nesting and removed the indirection of keyMap
import memoize from "proxy-memoize/dist/index.modern.js";
// comment the above import and replace memoize with the identity function and the code works as expected
// const memoize = (fn) => fn;
const state1 = {
ids: [1, 2],
entities: {}
};
const state2 = {
ids: [1, 2],
entities: {
1: "e-1",
2: "e-2",
3: "e-3"
}
};
const getEntityById = memoize(({ state, id }) => {
return state.entities[id];
});
const getCurrentEntities = memoize((state) => {
return state.ids.map((id) => getEntityById({ state, id }));
});
console.log(getCurrentEntities(state1));
console.log(getCurrentEntities(state2));
Thanks for the small reproduction!
#46 fixes the given case.
Can you play with it?
It may or may not fail with deeply nested selectors. In such a case, please open a new issue.
https://ci.codesandbox.io/status/dai-shi/proxy-memoize/pr/46 You can install the build locally. See "Local Install Instructions".
@dai-shi thanks for the quick turnaround. I tested and the issues I was experiencing previously seem to have been resolved!