Skip to content
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

Serialization of filterToQuery swallows symbol properties #10253

Closed
KilianB opened this issue Oct 2, 2024 · 3 comments
Closed

Serialization of filterToQuery swallows symbol properties #10253

KilianB opened this issue Oct 2, 2024 · 3 comments

Comments

@KilianB
Copy link

KilianB commented Oct 2, 2024

What you were expecting:

The object returned from AutocompleteInput's filterToQuery function is passed forward to the dataProvider as is.

What happened instead:

Properties with a symbol key are missing.

Steps to reproduce:

  1. Due to Stackblitz v4 issue template does not launch sample application  #10252 I had to build and run the sample first

  2. Open the terminal and CTRL + C the running dev server. run npm run build & npm run server

  3. Open the browser console

  4. Click on the Issue entry in the sidebar

  5. Click on the create button

  6. Type a string in the first box. Data arrives in the data provider
    image

  7. Type in the second box. Data does not arrive in the data provider. See that the param in the dataprovider is not logged at all. Most likely because it receives an empty filter object which does not trigger an update?

image

Related code:

<AutocompleteInput
  source="not_working"
  label="With Symbol"
  helperText="Filter with symbols work properly. View Console"
  filterToQuery={(searchText: string) => {
    const originalFilter = {
       [Symbol('CustomSymbol')]: searchText,
    };

    console.log('Symbol Filter returned in filterToQuery',originalFilter);
    return originalFilter;
  }}
  />

Other information:

Usecase: We use this setup as our filter setup is much more complex and we are supporting pretty much the entire range of SQL filters.

const OR = Symbol("OR");

interface Filter{
  [ressource: string]: FilterBase;
  [OR]? : FilterBase[]
}

Without using symbols typescript would complain about index signatures not matching up.

Environment

  • React-admin version: 4.16.20
  • React version: ^17.0.0
  • Browser: Chrome - All
@fzaninotto
Copy link
Member

Your stackblitz fails with "Undefined collection "issue""

Also, the problem with symbols comes from JavaScript, so there isn't anything we can do, unless you know a better serializer than JSON.stringify():

const OR = Symbol("OR");
JSON.stringify({ filter: OR })
// '{}'

@KilianB
Copy link
Author

KilianB commented Oct 3, 2024

I'll check out the Stackblitz once I the template is workable again. One option would be to forcibly reqrite symbols to be strings instead, but maybe this isn't really worth the effort and I just have to rethink my original approach.

const filter = {
  normal: "foo",
  [Symbol("key_sym")]: "bar",
};

const makeSymbolsSerializable = (obj: any) => {
  //Deep copy probably is overkill replace by Object.entries.reduce
  const cloned: Record<string, unknown> = structuredClone(obj);

  Object.getOwnPropertySymbols(obj).forEach((symbol) => {
    cloned[symbol.toString()] = obj[symbol];
  });
  return cloned;
};

console.log(JSON.stringify(makeSymbolsSerializable(filter)));

I believe here:

const permanentFilterSignature = JSON.stringify(permanentFilter);
?

@fzaninotto
Copy link
Member

Symbol support in JS isn't good enough for us to consider it a first-class citizen in filters. I suggest you wait until JSON.stringify() catches up (or submit a patch to v8 to add support yourself) and use constants instead.

So I'll close this issue. Thanks for the report anyway!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants