Error while trying to convert react-admin ImageInput file to Base64

Viewed 123

Following the official react-admin docs on how to implement file/image upload. I stumbled upon this error in Chrome console log:

enter image description here

It shows every time I call the update API method from the Edit page the code structure is as follows:

export const PlayerEdit = () => (
  <Edit>
    <SimpleForm>
      <TextInput source="id" />
      <NumberInput source="active" />
      <TextInput source="name" />
      <TextInput source="email" />
      <ImageInput source="profileImgShow" multiple={true} accept="image/png">
        <ImageField source="src" title="title" />
      </ImageInput>

      <TextInput source="new_password" />
      <TextInput source="repeat_password" />

      <DateInput source="register_date" />
      <DateInput source="createdAt" />
      <DateInput source="updatedAt" />
    </SimpleForm>
  </Edit>
);

and I wrapped the update API call with this helper function to add the upload functionality and facilitate the base64 convertion.

export const convertFileToBase64 = (file) => {
  console.log("rawFile", file.rawFile);
  return new Promise((resolve, reject) => {
    const reader = new FileReader();

    reader.onload = () => resolve(reader.result);
    reader.onerror = reject;
    reader.readAsDataURL(file.rawFile);
  });
};

/**
 * For posts update only, convert uploaded image in base 64 and attach it to
 * the `picture` sent property, with `src` and `title` attributes.
 */
const addUploadFeature = (requestHandler) => (resource, params) => {
  //console.log(resource, params);
  if (resource === "players") {
    // notice that following condition can be true only when `<ImageInput source="pictures" />` component has parameter `multiple={true}`
    // if parameter `multiple` is false, then data.pictures is not an array, but single object
    if (params.data.profileImgShow && params.data.profileImgShow.length) {
      // only freshly dropped pictures are instance of File

      const formerPictures = params.data.profileImgShow.filter(
        (p) => !(p.rawFile instanceof File)
      );

      const newPictures = params.data.profileImgShow.filter(
        (p) => p.rawFile instanceof File
      );

      return Promise.all(formerPictures.map(convertFileToBase64))
        .then((base64Pictures) =>
          base64Pictures.map((picture64) => ({
            src: picture64,
            title: `${newPictures.title}`,
          }))
        )
        .then((transformedNewPictures) =>
          requestHandler(resource, {
            ...params,
            data: {
              ...params.data,
              profileImgShow: [...transformedNewPictures, ...formerPictures],
            },
          })
        );
    }
  }
  // for other request types and resources, fall back to the default request handler
  //return requestHandler(type, resource, params);
};

export default addUploadFeature;

like this:

 update: addUploadFeature((resource, params) => {
    //console.log(params);
    return httpClient(`${apiUrl}/${resource}/${params.id}`, {
      method: "PUT",
      body: JSON.stringify(params.data),
    }).then(({ json }) => ({ data: json }));
  }),

but for some reason the convetFileToBase64 never get called, and my guess that's because the array of images/files supplied by ImageInput component have the type [Object] instead of [File] or [Blob] so the filtration by type process always fails:

  const newPictures = params.data.profileImgShow.filter(
    (p) => p.rawFile instanceof File
  );

Am I doing something wrong or it's the react-admin component supplying the wrong type of file? The attached image shows the result of formerPictures array being passed instead of newPictures because the filtration line return always empty array for newPictures and only formerPictures contian the file received from ImageInput.

the file I'm reciveing:

{
    "path": "logo192.png",
    "name": "logo192.png",
    "lastModified": 1635067661651,
    "lastModifiedDate": "2021-10-24T09:27:41.651Z",
    "webkitRelativePath": "",
    "size": 12630,
    "type": "image/png"
}

UPDATE:

I edited the tutorial sample on codesandbox.io to reproduce this issue, and oddly enough ImageInput returned an object of type [File] instead of [Object], however both react and react-dom versions were ^17.0.0 in sandbox and 18.0.0 on my machine, I downgraded to the older version (17.0.0) but still no luck rawFile still has the type of [Object] instead of [File] .

0 Answers
Related