dai-shi / proxy-memoize

Intuitive magical memoization library with Proxy and WeakMap

Home Page:http://proxy-memoize.js.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Nested proxy-memoized selectors

drop-evan opened this issue · comments

commented

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?

commented

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. 🤔

commented

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 🤔

commented

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".

commented

@dai-shi thanks for the quick turnaround. I tested and the issues I was experiencing previously seem to have been resolved!