没有 React <Mutation> 组件的 Apollo 突变

Apollo mutations without React <Mutation> component

Apollo 的 <Mutation> 组件通常运行良好,但有时您需要在 render() 方法之外调用突变。

在某些情况下,您可以像这样简单地传递变异函数:

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();
    };
}

但在其他情况下这不是一个非常合理的选择,例如:

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? */
    };
}

如何在这些场景中执行突变?

React Hooks 更新 (2020-12-18):

如果您使用的是 Apollo v3+ 和功能性 React 组件,现在有一个使用 Apollo 提供的 useMutation() 钩子的更简洁的解决方案:

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);
            }}
        />
    );
}

此外,官方文档说:

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

现在在 Apollo 中使用 hooks 优于 HOCs,所以如果可以的话使用 useMutation() 可能是个好主意。

您可以在以下位置阅读 useMutation 的文档: https://www.apollographql.com/docs/react/data/mutations/

原回答:

react-apollo 包含两个名为 graphql() and withApollo() 的 HOC,可用于完成此操作。

两者的区别在Apollo的文档中描述为:

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.

graphql() 被提供一个突变时,它将添加一个 this.props.mutate() 函数并且可以像这样使用:

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() 类似,但提供了一个 this.props.client 供您直接使用。可以这样执行突变:

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);