jaydenseric/apollo-upload-client

Version 18 doesn't work with React Native

lorinjacot opened this issue · 4 comments

To reproduce the error:

  1. Create a bare expo app with npx create-expo-app --template and choose the default options.
  2. Install the lastest version of this package: npm install apollo-upload-client
  3. Import it in App.js: import createUploadLink from 'apollo-upload-client/createUploadLink.mjs';
  4. Launch the app (I used the Android simulator) and get the following error: Unable to resolve "apollo-upload-client/createUploadLink.mjs" from "App.js

If I downgrade the package to version 17 and replace the import statement with import { createUploadLink } from 'apollo-upload-client'; , the app launches without error.

Why did you raise the issue in this project, instead of in the repo of the tooling you use to build for React Native? The burden is on your React Native tooling to support importing from a dependency that is a Node.js package that's in a standard and valid format.

As documented in the v18 major changes, React Native is no longer supported out of the box:

https://github.com/jaydenseric/apollo-upload-client/releases/tag/v18.0.0

You should be able to get it going tho, but I won't be able to assist.

As an idea, maybe make sure you uninstalled @types/apollo-upload-client? IDK how your RN tooling works but it's weird it struggles with a deep import; lots of packages provide deep imports.

Manual workaround for React Native:

import { Env } from '@/core/env';

const GQL_QUERY =
  'mutation ($file: Upload!) { uploadImage(input: {image: $file}) { imageId, imageUrl } }';

export function useGraphQLImageUpload() {
  const uploadImage = async (fileUri: string) => {
    const formData = new FormData();

    formData.append(
      'operations',
      JSON.stringify({
        query: GQL_QUERY,
        variables: {
          file: null,
        },
      })
    );

    // @ts-expect-error - FormData append method is not typed correctly
    formData.append('0', {
      uri: fileUri,
      name: 'image.jpg',
      type: 'image/jpeg',
    });

    formData.append('map', JSON.stringify({ '0': ['variables.file'] }));

    const response = await fetch(Env.API_URL, {
      method: 'POST',
      body: formData,
      headers: {
        'GraphQL-preflight': '1', // Required in my environment
      },
    });

    const result = await response.json();

    return result.data.uploadImage;
  };

  return {
    uploadImage,
  };
}

@Silon thanks for this solution but how we can implemented with apollo-client ? i have this error {"uri":"file:\/data\/user\/0\/care.heyme.mobile\/cache\/1132f9c2-579d-499b-bed9-79ff833b404b\/IMG_20240628_204010.jpg","type":"image\/jpeg"}; Expected type Upload; Could not get uploaded file, be sure to conform to GraphQL multipart request specification: https://github.com/jaydenseric/graphql-multipart-request-spec. Instead got: {"uri":"file:\/data\/user\/0\/care.heyme.mobile\/cache\/1132f9c2-579d-499b-bed9-79ff833b404b\/IMG_20240628_204010.jpg","type":"image\/jpeg"}.]

this is how i send it please help @jaydenseric @sashrika

const handleDocumentSelection = async () => {
  try {
    const res = await DocumentPicker.pick({
      type: [
        DocumentPicker.types.pdf,
        DocumentPicker.types.doc,
        DocumentPicker.types.docx,
        DocumentPicker.types.images,
      ],
      copyTo:
        Platform.OS === 'android' ? 'cachesDirectory' : 'documentDirectory',
    });

    const file = {
      uri: res[0].fileCopyUri,
      name: res[0].fileName,
      type: res[0].type
    };

    uploadImageMutation({variables: {file}})
      .then(({data}) => {
        console.log(data)
      })
      .catch(e => {
        console.log(e)
      });
  } catch (err) {
    //Handling any exception (If any)
    if (DocumentPicker.isCancel(err)) {
      // console.log('DocumentPicker cancled');
    } else {
      // alert('Unknown Error: ' + JSON.stringify(err));
      Sentry.captureException(err, {tags: {page: 'ContactFormScreen'}});
      throw err;
    }
  }
};