bytewitchcraft / apollo-absinthe-upload-link

A network interface for Apollo that enables file-uploading to Absinthe back ends.
61 stars 37 forks source link

Error: Network error: Object(...) is not a function #22

Closed ghost closed 5 years ago

ghost commented 5 years ago

Hi my mutation format looks like this:

import gql from 'graphql-tag'

export default (
  apolloClient,
  file,
) => {
  apolloClient
    .mutate({
      mutation: gql`
        mutation createGroup($file: Upload!) {
          createGroup(input: {file: $file}) {
            id
          }
        }
      `,
      variables: { file }
    })
}

I have an issue with sending my form data through the network, my error looks like this:

screen shot 2019-01-27 at 3 17 35 pm

Here is how I initialize my apollo client:

  return new ApolloClient({
    connectToDevTools: process.browser,
    ssrMode: !process.browser, // Disables forceFetch on the server (so queries are only run once)
    link: ApolloLink.from([
      onError(({ graphQLErrors, networkError }) => {
        if (graphQLErrors) {
          graphQLErrors.map(({ message, locations, path }) => console.log(
            `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
          ));
        }
        if (networkError) {
          console.log(`[Network error]: ${networkError}`);
        }
      }),
      authLink,
      uploadLink
    ]),
    cache: new InMemoryCache().restore(initialState || {})
  })

Where my authLink looks like this:

  const authLink = setContext((_, { headers }) => {
    const token = getToken()
    return {
      headers: {
        ...headers,
        authorization: token ? `Bearer ${token}` : ''
      }
    }
  })

And my uploadLink looks like this:

  const uploadLink = createUploadLink({
    uri: '/api/graphql',
    credentials: 'same-origin'
  })

Both my api and client are sitting behind an nginx server that routes the relevant requests to their specific endpoints. Is there any nginx setup i need to do to get this working or is this more of either a frontend setup issue or an api setup issue

Honestly not sure what is wrong, I could do my other mutations just fine

ihorkatkov commented 5 years ago

I'm not sure how do you use it but take a look at my example

/* eslint-disable jsx-a11y/label-has-for,react/destructuring-assignment */
import React from 'react'
import { graphql } from 'react-apollo'
import gql from 'graphql-tag'
import { pipe, prop } from 'ramda'

type FileInputProps = {
  label: string,
  onChange: Function,
  required: boolean,
}

const FileInput = (props: FileInputProps) => (
  <div className="up-pic-btn-container upload-btn">
    <label>
      <input type="file" {...props} />
      {props.label}
    </label>
  </div>
)

type SingleUploaderProps = {
  mutate: Function,
  onUpload: Function,
  label: string,
}

const SingleUploader = (props: SingleUploaderProps) => {
  const handleChange = ({ target }) =>
    target.validity.valid &&
    props
      .mutate({
        variables: { file: target.files[0] },
      })
      .then(
        pipe(
          prop('data'),
          prop('uploadPhoto'),
          props.onUpload,
        ),
      )

  return <FileInput required onChange={handleChange} {...props} />
}

const query = gql`
  mutation($file: Upload!) {
    uploadPhoto(photo: $file) {
      id
      url
    }
  }
`

export default graphql(query)(SingleUploader)
ghost commented 5 years ago

thanks i'll try it out

UPDATE: still getting the same error

My guess is that it is sitting behind an nginx server and that is what is causing the issue with file uploads. Another reason could be that I'm using nextjs and there is some server side vs client side url discrepancy. Anybody else has any idea?

ghost commented 5 years ago

I sincerely think there might be something wrong with the execution of the function. Here is what I found, please investigate if this is true.

I have a function that returns a nested Mutation component as shown:

export default (props) =>
  <div className="discover col-fs-c">
    <FeaturedGroups />
    <Mutation
      mutation={mutation}>
      {mutate => {
        return <input type="file" onChange={e => onChange(e, mutate)} />;
      }}
    </Mutation>
  </div>

My graphql-tag mutation is as follows:

const mutation = gql`
  mutation createCircle(
                        $file: Upload!,
                        $day: String!,
                        $description: String!,
                        $duration: Int!,
                        $end: DateTime!,
                        $start: DateTime!,
                        $name: String!,
                        $price: Float!,
                        $spaceType: String!,
                        $programLength: Int!,
                        $location: String!,
                        $time: String!
  ) {
    createCircle(
                input: {
                  file: $file,
                  day: $day,
                  description: $description,
                  duration: $duration,
                  end: $end,
                  start: $start,
                  name: $name,
                  price: $price,
                  spaceType: $spaceType,
                  programLength: $programLength,
                  location: $location,
                  time: $time
                }
    ) {
      id
    }
  }
`

I have an onChange handler function to execute the mutation:

const onChange = async (e, uploadFile) => {
  const {
    currentTarget: { validity, files }
  } = e;

  if (validity.valid && files) {
      const variables = {
        variables: {
          file: files[0],
          day: "Monday",
          description: "Hello World",
          duration: 60,
          end: "2018-05-17T12:11:06.3684072Z",
          start: "2018-05-17T12:11:06.3684072Z",
          name: "Sample Group",
          price: 45,
          spaceType: "organization",
          programLength: 12,
          location: "Williamsburg",
          time: "3:40"
        }
      }
      uploadFile(variables)
  }
}

I am pretty sure I am following the way I was supposed to pass in my variables object. Please confirm if this is not the way to pass in my variables.

Ultimately, uploadFile(variables) is called and returns this error:

screen shot 2019-01-31 at 3 40 52 am

So either the way I am passing in variables is wrong, or there is something buggy going on with the mutate function.

juddey commented 5 years ago

I get the same issue with v1.5.0..... This does not happen in 1.2.2 (which i have just downgraded to to make things go.)

ihorkatkov commented 5 years ago

Hey @juddey, that's strange. I will take a look more precisely

giovankabisano commented 3 years ago

Any update on this issue? @ihorkatkov @sc4224