0
votes

Background: I'm building a Shopify app using React, NextJS, and GraphQL. The functionality is to add an extra privateMetafield with a value for each selected product.

The problem: I'm trying to create or update (if privateMetafield exists) with Mutation using React-Apollo. I have tried to run the GraphQL mutation in Insomnia (like postman for GraphQL) and it works. But when I add it to my code I don't get the GraphQL to receive the mutation data. Instead, I get this error message:

Unhandled Runtime Error
Error: GraphQL error: Variable $input of type PrivateMetafieldInput! was provided invalid value for privateMetafields (Field is not defined on PrivateMetafieldInput), namespace (Expected value to not be null), key (Expected value to not be null), valueInput (Expected value to not be null)

Insomnia Successful GraphQL test (what it should be like) GraphQL test

edit-products.js

...
import gql from 'graphql-tag';
import { Mutation } from 'react-apollo';
...
const UPDATE_EMISSION = gql`
    mutation($input: PrivateMetafieldInput!) {
        privateMetafieldUpsert(input: $input) {
        privateMetafield {
            namespace
            key
            value
        }
        }
    }
`;
...
class EditEmission extends React.Component {
    state = {
        emission: '',
        id: '',
        showToast: false,
    };

    render() {
        const { name, emission, id } = this.state;
        return (
            <Mutation
                mutation={UPDATE_EMISSION}
            >
                {(handleSubmit, { error, data }) => {
                    const showError = error && (
                        <Banner status="critical">{error.message}</Banner>
                    );
                    const showToast = data && data.productUpdate && (
                        <Toast
                            content="Sucessfully updated"
                            onDismiss={() => this.setState({ showToast: false })}
                        />
                    );
                    return (
                        <Frame>
                            ...           <Form>
                                                        <TextField
                                                            prefix="kg"
                                                            value={emission}
                                                            onChange={this.handleChange('emission')}
                                                            label="Set New Co2 Emission"
                                                            type="emission"
                                                        />
                                                   ...
                                            <PageActions
                                                primaryAction={[
                                                    {
                                                        content: 'Save',
                                                        onAction: () => {
                                                            const item = store.get('item');
                                                            const id = item.id;
                                                            const emissionVariableInput = {
                                                                owner: id,
                                                                privateMetafields: [
                                                                    {
                                                                        namespace: "Emission Co2",
                                                                        key: "Co2",
                                                                        valueInput: {
                                                                            value: emission,
                                                                            valueType: "INTEGER"
                                                                        }
                                                                    }
                                                                ]
                                                            };
                                                            console.log(emissionVariableInput)
                                                            handleSubmit({
                                                                variables: { input: emissionVariableInput },
                                                            });
                                                        }
                                                    }
                                                ]}
                                                secondaryActions={[
                                                    {
                                                        content: 'Remove emission'
                                                    }
                                                ]}
                                            />
                                        </Form>
                                 ...
            </Mutation>
        );
    }

    handleChange = (field) => {
        return (value) => this.setState({ [field]: value });
    };
}

export default EditEmission;

I get this in the console when I log emissionVariableInput, which looks correct. But why is the data not passed properly to the GraphQL mutation and how do I fix it?

enter image description here

I expect the GraphQL mutation to be successful and create/update a privateMetafield owned by a product.

Thanks in advance!

1
I could be wrong but should it be valueInput: $input or input: $valueInput?miguelsolano
@miguelsolano Thanks for the question. I tried to shift it but it led to this error instead: valueInput does not exist for PrivateMetafieldInput.9minday

1 Answers

1
votes

You have different shapes for input in your examples. In Insomnia you pass:

   {
     owner: id,
     namespace: "Emission Co2",
     key: "Co2",
     valueInput: {
      value: emission,
      valueType: "INTEGER"
     }
   }

While in the code your input looks like:

{
  owner: id,
  privateMetafields: [{
    namespace: "Emission Co2",
    key: "Co2",
    valueInput: {
     value: emission,
     valueType: "INTEGER"
    }
  }]
};