How to run a mutation on mount with React Apollo 2.1's Mutation component? : <p>We are currently moving from <a href="https://facebook.github.io/relay/docs/en/introduction-to-relay.html" rel="noreferrer">Relay</a> to <a href="https://www.apollographql.com/docs/react/" rel="noreferrer">React Apollo 2.1</a> and something I'm doing seems fishy.</p>

<p><strong>Context:</strong> Some components must only be rendered if the user is authenticated (via an API key), so there is an <code>Authenticator</code> component guarding the rest of the tree.</p>

<p>In <code>App.js</code>, it gets used like this (obviously all snippets below are minimal examples):</p>

<pre><code>import React from 'react';
import Authenticator from './Authenticator';
import MyComponent from './MyComponent';

export default function App({ apiKey }) {
  return (
    &lt;Authenticator apiKey={apiKey}
      render={({ error, token }) =&gt; {
        if (error) return &lt;div&gt;{error.message}&lt;/div&gt;;
        if (token) return &lt;MyComponent token={token} /&gt;;
        return &lt;div&gt;Authenticating...&lt;/div&gt;;
      }}
    /&gt;
  );
}
</code></pre>

<p>If authentication succeeds, <code>MyComponent</code> gets rendered.
<code>Authentication</code> sends the authentication mutation to the server when rendered/mounted for the first time and calls the <a href="https://reactjs.org/docs/render-props.html" rel="noreferrer">render prop</a> accordingly.
<code>Authentication.js</code> looks as such:</p>

<pre><code>import gql from 'graphql-tag';
import React from 'react';
import { Mutation } from 'react-apollo';

const AUTH_MUTATION = gql`mutation Login($apiKey: String!) {
  login(apiKey: $apiKey) {
    token
  }
}`;

export default function Authenticator({ apiKey, render }) {
  return (
    &lt;Mutation mutation={AUTH_MUTATION} variables={{ apiKey }}&gt;
      {(login, { data, error, called }) =&gt; {
        if (!called) login(); // ⚠️ This seems sketchy ⚠️

        const token = (data &amp;&amp; data.login.token) || undefined;
        return render({ error, token });
      }}
    &lt;/Mutation&gt;
  );
}
</code></pre>

<p>That <code>if (!called) login();</code> is what is giving me pause. If I don't specify <code>if (!called)</code>, the UI becomes epileptic and sends thousands of requests (which makes sense, calling <code>login()</code> causes <code>render()</code> to re-run), but is that how it's supposed to be used?</p>

<p>It seems like the <a href="https://www.apollographql.com/docs/react/react-apollo-migration.html#query-component" rel="noreferrer"><code>Query</code> component equivalent</a> differs in that simply rendering it emits the request. and I am wondering if there is a way to apply the same mechanism to <code>Mutation</code>, which requires calling the mutate function as part of the render prop.</p>

<p>The Relay equivalent of the snippet above does exactly what React Apollo's <code>Query</code> does on <code>Mutation</code>:</p>

<pre><code>// Authentication.js

import React from 'react';
import { graphql, QueryRenderer } from 'react-relay';
import { Environment } from 'relay-runtime';

// Hiding out all the `Environment`-related boilerplate
const environment = return new Environment(/* ... */);

const AUTH_MUTATION = graphql`mutation Login($apiKey: String!) {
  login(apiKey: $apiKey) {
    token
  }
}`;

export default function Authenticator({ apiKey, render }) {
  return (
    &lt;QueryRenderer query={AUTH_MUTATION} variables={{ apiKey }}
      render={render}
    /&gt;
  );
}


// App.js

import React from 'react';
import Authenticator from './Authenticator';
import MyComponent from './MyComponent';

export default function App({ apiKey }) {
  return (
    &lt;Authenticator apiKey={apiKey}
      render={({ error, props }) =&gt; {
        if (error) return &lt;div&gt;{error.message}&lt;/div&gt;;
        if (props) return &lt;MyComponent token={props.loginAPI.token)} /&gt;;
        return &lt;div&gt;Authenticating...&lt;/div&gt;;
      }}
    /&gt;
  );
}
</code></pre>
