0

I'm trying to pass a class instance, which has private members, through to a navigate call for react-router-dom, through its state key.

The class instance I'm trying to pass:

class Cart{
  #contents;
  add(itemName){
    const existingEntry = this.#contents[itemName];
    const oldCount = existingEntry?.count;
    const newCount = oldCount+1;
    this.#contents[itemName] = {name: itemName, count: newCount};
    return this;
  }
  get contents(){
    return JSON.parse(JSON.stringify(this.#contents))
  }
}

Passing the instance to navigate:

function SomeComponent(){
  // some react code...
  const navigate = useNavigate();

  const handleClick = () => {
    const item = 'Bananas';
    const cart = new Cart().add(item); 
    navigate('/someURL', { state: {cart} });
  }
  // some react code...   
}

But when I access it from the consumer component using useLocation, it turns into an empty object. This means I can't access the contents of the class, since the recieved object is just a plain object, and has no getter functions, like the class instance I passed in.

function ConsumerComponent(){
  //some react code...
  const { state } = useLocation();
  console.log(state.cart);  // '{}'

  //some react code...
}

How can I pass it to navigate, while getting back the same instance, instead of a shallow copied object?

EDIT 1

Here is a link to a codesandbox that demonstrates the issue. Strangely enough, the code works in the sandbox; and I get the class instance at the ConsumingComponent. But try downloading the sandbox locally and running it. The ConsumingComponent will only be able to access a plain object(as hypothesized by @Drew Reese) in the comments. I would be inclined to believe that

"only JSON/string serializable objects can be passed via route state"

but I can't wrap my head around this discrepancy in behaviour between the sandbox and the local instance. Any hypotheses, ideas or even conjecture is greatly appreciated.

TMI: I'm trying to implement a checkout fn which accepts a Cart object as a parameter, and navigates to the checkout page @'/checkout', while passing the cart inside the navigate route state. The reason I wish to do so, is because the checkout fn is intended to checkout single objects(similar to a Buy now button on amazon), and hence I don't really want to store the Cart in my global state management system, since its a single-use class instance.

sayandcode
  • 1,775
  • 1
  • 11
  • 24
  • this should work can you please provide a sandbox link of this code? – Talha Fayyaz Aug 10 '22 at 12:02
  • @TalhaFayyaz Strangely enought, I can't seem to recreate it on codeSandbox. Essentially all the private members are getting filtered out. Any idea why this might be happening, or how to isolate the problem? – sayandcode Aug 10 '22 at 13:23
  • I only see one function in a class that should be accessible. – Talha Fayyaz Aug 10 '22 at 13:52
  • 1
    IIRC I am fairly certain that only JSON/string serializable objects can be passed via route state. It's not clear at all though why you are trying to pass a Javascript class through. What is the use case? What problem are you trying to solve? – Drew Reese Aug 10 '22 at 20:55
  • @DrewReese Exactly! That seems to be the behaviour locally. But for some reason class instances can be passed on codesandbox.io. I have added more context about why I need this functionality in the edited question. Pls check. – sayandcode Aug 11 '22 at 07:46
  • @TalhaFayyaz I apologize for the incomplete class definition earlier. The updated answer contains more contextual info about the class, and why it isn't possible to access from useLocation hook – sayandcode Aug 11 '22 at 07:48
  • Did you find a solution to this? Coming across a similar issue and but I can send an instance of `FileSystemDirectoryHandle` and access its functions but not a custom made class. – Josh Hales Sep 11 '22 at 08:43
  • I've found that using `Object.setPrototype()` can be a fix but doesn't really answer the discrepancy issue which is really bugging me. – Josh Hales Sep 11 '22 at 08:52

0 Answers0