Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apollo mutations without React <Mutation> component

Tags:

react-apollo

Apollo's <Mutation> component often works well, but sometimes you need to call mutations outside of the render() method.

In some cases you can simply pass along the mutation function like so:

import React, { Component } from "react";
import { DO_MUTATION } from "./mutations";
import { Mutation } from "react-apollo";

export default class MyComponent extends Component {
    render() {
        return (
            <Mutation mutation={DO_MUTATION}>
                {(doMutation) => (
                    <Button
                        onPress={() => {
                            this.handleSomething(doMutation);
                        }}
                    />
                )}
            </Mutation>
        );
    }

    handleSomething = (doMutation) => {
        /* DO SOME STUFF */
        doMutation();
    };
}

But in other cases this is not a very reasonable option, for example:

import React, { Component } from "react";
import { DO_MUTATION } from "./mutations";
import { Mutation } from "react-apollo";

import SomeLibrary from "SomeLibrary";

export default class MyComponent extends Component {
    render() {
        return (
            <Mutation mutation={DO_MUTATION}>
                {(doMutation) => (
                    <Button
                        onPress={() => {
                            SomeLibrary.addListener(this.listenerHandler);
                        }}
                    />
                )}
            </Mutation>
        );
    }

    listenerHandler = () => {
        /* HOW DO I DO MUTATIONS HERE? */
    };
}

How can mutations be performed in these scenarios?

like image 982
twiz Avatar asked Jun 02 '19 17:06

twiz


1 Answers

Update for React Hooks (2020-12-18):

If you are using Apollo v3+ and functional React components, there is now a much cleaner solution using the useMutation() hook provided by Apollo:

import React from "react";
import { useMutation } from "@apollo/client";
import SomeLibrary from "SomeLibrary";

import { DO_MUTATION } from "./mutations";

export default function MyComponent() {
    const [doMutation, { data }] = useMutation(DO_MUTATION);

    let listenerHandler = () => {
        doMutation({
            variables: {
                some_var: "some_val",
            },
        });
    };

    return (
        <button
            onPress={() => {
                SomeLibrary.addListener(listenerHandler);
            }}
        />
    );
}

Also, the official docs say:

The useMutation React hook is the primary API for executing mutations in an Apollo application.

Using hooks is now preferred over HOCs in Apollo, so it is probably a good idea to use useMutation() if you can.

You can read the documentation for useMutation at: https://www.apollographql.com/docs/react/data/mutations/

Original answer:

react-apollo includes two HOCs called graphql() and withApollo() that can be used to accomplish this.

The difference between the two is described in Apollo's documentation as:

If you are wondering when to use withApollo() and when to use graphql() the answer is that most of the time you will want to use graphql(). graphql() provides many of the advanced features you need to work with your GraphQL data. You should only use withApollo() if you want the GraphQL client without any of the other features.

When graphql() is provided a mutation it will add a this.props.mutate() function and can be used like this:

import React, { Component } from "react";
import { DO_MUTATION } from "./mutations";
import { graphql } from "react-apollo";

import SomeLibrary from "SomeLibrary";

export class MyComponent extends Component {
    render() {
        return (
            <Button
                onPress={() => {
                    SomeLibrary.addListener(this.listenerHandler);
                }}
            />
        );
    }

    listenerHandler = () => {
        this.props.mutate({
            variables: {
                some_var: "some_val",
            },
        });
    };
}
export default graphql(DO_MUTATION)(MyComponent);

withApollo() is similar but instead provides a this.props.client for you to use directly. A mutation can be performed like this:

import React, { Component } from "react";
import { DO_MUTATION } from "./mutations";
import { withApollo } from "react-apollo";

import SomeLibrary from "SomeLibrary";

export class MyComponent extends Component {
    render() {
        return (
            <Button
                onPress={() => {
                    SomeLibrary.addListener(this.listenerHandler);
                }}
            />
        );
    }

    listenerHandler = () => {
        this.props.client.mutate({
            mutation: DO_MUTATION,
            variables: {
                some_var: "some_val",
            },
        });
    };
}
export default withApollo(MyComponent);
like image 73
twiz Avatar answered Oct 10 '22 06:10

twiz