React-apollo: Optional input is set to null

Created on 23 Jan 2018  路  11Comments  路  Source: apollographql/react-apollo

Hello. I have a "users" request with userFilterInput which is optional. In my case i do not set the filter. Apollo will send this request to the server

{"operationName":"users","variables":{"userFilterInput":null},"query":"query users($userFilterInput: UserFilterInput) {\n  users(userFilterInput: $userFilterInput) {\n    id\n    email\n    lastName\n    firstName\n    __typename\n  }\n}\n"}

Why userFilterInput is set to null and not to undefined? Bellow you can find my code and you can see that I did not set up any filter.

export const USERS = gql`
  query users($userFilterInput: UserFilterInput) {
    users(userFilterInput: $userFilterInput) {
      id
      email
      lastName
      firstName
    }
  }
`;

export default graphql(USERS, {
  options: () => ({
    notifyOnNetworkStatusChange: true,
  }),
  props: ({ data: { loading, error, users, networkStatus, refetch } }) => ({
    usersLoading: loading,
    usersError: error,
    usersRefetch: refetch,
    users,
    networkStatus,
  }),
});

Most helpful comment

I agree with @jurajkrivda .

Nullable input when not presented within the query variables in apollo client, is getting called with null value.

Client should not pass the whole input as null, it should omit it completely or pass it with undefined.

Passing null may mean explicitly null the input. Same applied to input fields, so the server may react on explicitly resetting the value (presented in the input with null or do not handle it if omitted). As discussed https://github.com/apollographql/apollo-android/issues/652 or https://github.com/apollographql/apollo-codegen/issues/81

All 11 comments

I agree with @jurajkrivda .

Nullable input when not presented within the query variables in apollo client, is getting called with null value.

Client should not pass the whole input as null, it should omit it completely or pass it with undefined.

Passing null may mean explicitly null the input. Same applied to input fields, so the server may react on explicitly resetting the value (presented in the input with null or do not handle it if omitted). As discussed https://github.com/apollographql/apollo-android/issues/652 or https://github.com/apollographql/apollo-codegen/issues/81

I have a similar problem. I was able to solve it with a utility function that passes only into the request variables:

utils.js

// handle empty string
export const graphqlFriendlyObject = x => Object.keys(x).reduce((p, c) => {
  p[c] = x[c] || undefined;
  return p;
}, {});

And then in my mutation:

import {graphqlFriendlyObject} from "../../Utils";
...
graphql(MutationUpdateChild, {
    options: {
      refetchQueries: [{ query: QueryAllChildren }],
      update: (proxy, { data: { updateChild } }) => {
        const query = QueryAllChildren;
        const data = proxy.readQuery({ query });

        // find item to update
        const updateIndex = data.listChildren.items.findIndex(
          child => child.id === updateChild.id
        );

        // splice in update
        data.listChildren.items.splice(updateIndex, 1, updateChild);
        proxy.writeQuery({ query, data });
      }
    },
    props: props => ({
      updateChild: child => {
        const fChild = graphqlFriendlyObject(child);

        return props.mutate({
          variables: { ...fChild, expectedVersion: fChild.version },
          optimisticResponse: () => ({
            updateChild: {
              ...child,
              __typename: "Child"
            }
          })
        });
      }
    })
  }),

Something new on this ?

I recently upgraded my package.json configuration (for a professional project) and it led to a huge backward incompatibility. I used to handle "null" as an explicit value ("set this field to null in the database") and undefined as a way to tell the server there's nothing to change, it's just an optional parameter that was omitted. My fix was just to force the install of an earlier version of the apollo server.

By setting optional parameters to null, how do you even make the difference between omitted optional parameters and the actual value "null" ?

We're having the same issue, any thoughts ?

Same - we check every version against our test suite and have not been able to update past react-apollo 2.1.11 due to this issue. I believe that is the newest version that correctly implements the graphql spec as @dacz mentioned above.

Tested with 2.4.1 and 2.5.0 beta and issue still persists (is easy to repro with the the info in the issue description). Would love to know if this is intended behavior or not.

Same, very boring !!
Thx @zamiang to check for every new version ;)

Same issue, would love an update!

Playing with a gross workaround until something more elegant is suggested. In this example, I'm trying to rehydrate my client cache with some remote data. With all of these fields being optional, if no remote data exist, I'm calling the mutation without some variables and it's setting them to null. In your writeQuery data, you can have some ternary logic to handle default values or set as undefined.

export const rehydrateDetailsCache = (
  _obj,
  {
    flyerTitle,
    participationFee,
    eventLocation,
    registrationDeadlineRequired,
    deadlineDate,
  },
  { cache }
) => {
  cache.writeQuery({
    query: DETAILS_QUERY,
    data: {
      campaignDetails: {
        __typename: 'CampaignDetails',
        flyerTitle,
        participationFee,
        eventLocation,
        registrationDeadlineRequired: registrationDeadlineRequired
          ? registrationDeadlineRequired
          : true,
        deadlineDate: deadlineDate ? deadlineDate : undefined,
      },
    },
  });
  return null;
};

This is now an issue for more than a year. Several threads were opened about it on Github. Still nothing changed. We didn't even get a proper explanation.

This was a major break in regards to backward compatibility and a lot of people are concerned with this.

Can we get an answer, please ?

@jurajkrivda have you tried to use the default scalar ID? type as workaround?

Setting optional inputs to null also breaks the default value set on an apollo server - seems rather counter intuitive.

Was this page helpful?
0 / 5 - 0 ratings