api-platform / admin

A beautiful and fully-featured administration interface builder for hypermedia APIs
https://api-platform.com/docs/admin/
MIT License
477 stars 131 forks source link

Cannot unset any property on 3.4.7 #559

Closed RozbehSharahi closed 1 month ago

RozbehSharahi commented 1 month ago

API Platform version(s) affected: 3.4.7

Description
I have a very basic setup of the admin running.

import React from "react";
import { createRoot } from "react-dom/client";
import {
  HydraAdmin,
  hydraDataProvider as baseHydraDataProvider,
  fetchHydra as baseFetchHydra,
} from "@api-platform/admin";
import { parseHydraDocumentation } from "@api-platform/api-doc-parser";
import { authProvider } from "./authProvider";
import { API_ENDPOINT } from "./config/config";

const documentationParser = async () => {
  await authProvider.getTokenWithRefresh();

  return await parseHydraDocumentation(API_ENDPOINT, {
    headers: (): {} | { Authorization: string } => {
      const token = authProvider.getToken();
      return token ? { Authorization: `Bearer ${token}` } : {};
    },
  });
};

const dataProvider = baseHydraDataProvider({
  entrypoint: API_ENDPOINT,
  httpClient: async (url, options = {}) => {
    options.headers = options.headers || new Headers();
    const token = await authProvider.getTokenWithRefresh();

    if (token) {
      options.user = { authenticated: true, token: `Bearer ${token}` };
    }

    return baseFetchHydra(url, options);
  },
  apiDocumentationParser: documentationParser,
});

const Admin = () => (
  <HydraAdmin
    entrypoint={API_ENDPOINT}
    dataProvider={dataProvider}
    authProvider={authProvider}
  ></HydraAdmin>
);

createRoot(document.getElementById("root") as any).render(<Admin />);

How to reproduce

Basically in version 3.4.7 you can try to empty any field of any entity and you should receive:

Cannot read properties of null (reading 'rawFile')

Possible Solution
I don't know.

My first guess is that in the following code a check for object is not sufficient as null also is typeof object

const findFile = (values: any[]): object | undefined =>
  values.find((value) =>
    Array.isArray(value)
      ? findFile(value)
      : typeof value === 'object' && value.rawFile instanceof File,
  );

Additional Context

I am not a react dev and also have very few experience with this tool. If this is not a bug but rather an issue of my setup and you can not reproduce it => i am sorry.

The reason I decided to write this issue is, that after extending tryouts i realized that the issue does not happen on 3.4.6 and the error where it comes from useOnSubmit is a file that was recently introduced.

PawelSuwinski commented 1 month ago

My first guess is that in the following code a check for object is not sufficient as null also is typeof object

Good catch! Reproduced, optional chaining fix it:

const findFile = (values: any[]): object | undefined =>
// ...
      : typeof value === 'object' && value?.rawFile instanceof File,
  );

The reason I decided to write this issue is, that after extending tryouts i realized that the issue does not happen on 3.4.6 and the error where it comes from useOnSubmit is a file that was recently introduced.

Mostly it is just common code moved to one place to make a hook, however this part needed refactoring to be children agnostic.