proxy-memoize: Returns object which not equal by ref

I want to optimize my calculations with simplest memoization using ref but faced with problem that memoized state props not equal to previous by ref. Why? Can I compare these values by ref?

const memoize = require('proxy-memoize').memoize;

const reduxState = {
  bookByName: {},
};

const selector = memoize((state) => {
  if (state.bookByName !== reduxState.bookByName) {
    console.log('Why not equal?');
  }
});

selector(reduxState);

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 34 (34 by maintainers)

Most upvoted comments

I added a failing test in #64. It looks like the bug is in v2.0.1, but not in v2.0.0. So, #60 was a bad fix, as I implied: https://twitter.com/dai_shi/status/1613867634952654849

Reduced further: https://codesandbox.io/s/frosty-sun-cssreh?file=/src/App.js

const { memoize } = require("proxy-memoize");
// const memoize = (fn) => fn;

const reduxState = {
  strangeObject: {},
  bookPrices: {
    book1: 150,
    book2: 50
  }
};

const selectBook2Price = memoize((state) => state.bookPrices.book2);

const selectBook2RoundPrice = memoize((state) => {
  const { strangeObject } = state;
  return selectBook2Price(state);
});

const selectPricesSum = memoize((state) => {
  return state.bookPrices.book1 + selectBook2RoundPrice(state);
});

selectBook2RoundPrice(reduxState);

const result1 = selectPricesSum(reduxState);

const nextState = {
  ...reduxState,
  bookPrices: {
    ...reduxState.bookPrices,
    book2: 90
  }
};

const result2 = selectPricesSum(nextState);

console.log(result1, result2);

export default () => null;

https://codesandbox.io/s/keen-heisenberg-4pg6u0?file=/src/App.js

This is so much for today. Next step would be to eliminate createSelectorById.

const { memoize } = require("proxy-memoize");

const reduxState = {
  strangeObject: {},
  books: {
    book1: {
      price: 150,
      name: "book1"
    },
    book2: {
      price: 50,
      name: "book2"
    }
  }
};

const createSelectorById = (getById) => {
  let memoizedSelectorById = {};
  return (id) => {
    const memoizedSelector = memoizedSelectorById[id];
    if (memoizedSelector) {
      return memoizedSelector;
    }
    const nextMemoizedSelector = memoize(getById(id));
    memoizedSelectorById[id] = nextMemoizedSelector;
    return nextMemoizedSelector;
  };
};

const getPriceSelector = createSelectorById((name) => ({ books }) => {
  const book = books[name];
  return book.price;
});

const getRoundPriceSelector = createSelectorById((name) => (state) => {
  const { strangeObject } = state;
  return getPriceSelector(name)(state);
});

const selectPricesSum = memoize((state) => {
  return Object.values(state.books).reduce((acc, book) => {
    return acc + getRoundPriceSelector(book.name)(state);
  }, 0);
});

getRoundPriceSelector("book1")(reduxState);
getRoundPriceSelector("book2")(reduxState);
getPriceSelector("book1")(reduxState);
getPriceSelector("book2")(reduxState);

const result1 = selectPricesSum(reduxState);

const nextState = {
  ...reduxState,
  books: {
    ...reduxState.books,
    book2: {
      ...reduxState.books.book2,
      price: 90
    }
  }
};

const result2 = selectPricesSum(nextState);

console.log(result1, result2);

export default () => null;

so yea, bug still here.

Gotcha. Yes, I understand it should output 200, 240.

I don’t used reselect.

Oh, my misunderstanding then. It looks to me there’s more efficient way in proxy-memoize. Anyway, our plan is:

  1. fix wrong behavior or a bug if any
  2. fix performance issue
  3. possibly look for better practice