如何使用React Apollo 2.1的Mutation组件在mount上运行变异? [英] How to run a mutation on mount with React Apollo 2.1's Mutation component?

查看:139
本文介绍了如何使用React Apollo 2.1的Mutation组件在mount上运行变异?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们目前正在从接力转到< a href =https://www.apollographql.com/docs/react/\"rel =noreferrer> React Apollo 2.1 和我正在做的事似乎很可疑。

We are currently moving from Relay to React Apollo 2.1 and something I'm doing seems fishy.

上下文:只有在用户通过身份验证(通过API密钥)后才能呈现某些组件,因此有一个 Authenticator 组件保护树的其余部分。

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

App.js 中,它被这样使用(显然所有下面的代码段是最小的例子):

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

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

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

如果验证成功, MyComponent 被渲染。
身份验证首次呈现/挂载时将身份验证突变发送到服务器并调用相应地渲染道具
Authentication.js 看起来像这样:

If authentication succeeds, MyComponent gets rendered. Authentication sends the authentication mutation to the server when rendered/mounted for the first time and calls the render prop accordingly. Authentication.js looks as such:

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 (
    <Mutation mutation={AUTH_MUTATION} variables={{ apiKey }}>
      {(login, { data, error, called }) => {
        if (!called) login(); // ⚠️ This seems sketchy ⚠️

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

if(!called)login(); 是什么让我暂停。如果我没有指定 if(!called),则UI变得癫痫并发送数千个请求(这是有道理的,调用 login()导致 render()重新运行),但它应该如何使用?

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

好像是 查询组件等效的不同之处在于只是呈现它发出请求。我想知道是否有办法将相同的机制应用于 Mutation ,这需要将mutate函数作为渲染道具的一部分来调用。

It seems like the Query component equivalent differs in that simply rendering it emits the request. and I am wondering if there is a way to apply the same mechanism to Mutation, which requires calling the mutate function as part of the render prop.

上面代码段的Relay相当于React Apollo的查询 Mutation 的影响:

The Relay equivalent of the snippet above does exactly what React Apollo's Query does on Mutation:

// 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 (
    <QueryRenderer query={AUTH_MUTATION} variables={{ apiKey }}
      render={render}
    />
  );
}


// App.js

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

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


推荐答案

对或错,Apollo制作关于如何使用查询和突变的一些假设。按照惯例,查询只会在突变时获取数据,好吧,变异数据。阿波罗进一步采用这种模式,并假设突变将在某种行动中发生。所以,就像你观察到的那样, Query 在mount上获取查询,而 Mutation 传递一个函数来实际获取变异。

Right or wrong, Apollo makes some assumptions about how queries and mutations are used. By convention queries only fetch data while mutations, well, mutate data. Apollo takes that paradigm one step further and assumes that mutations will happen in response to some sort of action. So, like you observed, Query fetches the query on mount, while Mutation passes down a function to actually fetch the mutation.

从这个意义上说,你已经偏离了应该使用这些组件的方式。

In that sense, you've already deviated from how these components are "supposed to be used."

我认为你的方法没有任何直接的错误 - 假设被称为永远不会被重置,你的组件应该按预期运行。但是,您可以创建一个简单的包装器组件来利用 componentDidMount

I don't think there's anything outright wrong with your approach -- assuming called never gets reset, your component should behave as intended. As an alternative, however, you could create a simple wrapper component to take advantage of componentDidMount:

class CallLogin extends React.Component {
  componentDidMount() {
    this.props.login()
  }

  render() {
    // React 16
    return this.props.children
    // Old School :)
    // return <div>{ this.props.children }</div>
  }
}

export default function Authenticator({ apiKey, render }) {
  return (
    <Mutation mutation={AUTH_MUTATION} variables={{ apiKey }}>
      {(login, { data, error }) => {
        const token = (data && data.login.token) || undefined;
        return (
          <CallLogin login={login}>
            {render({ error, token })}
          </CallLogin>
        )
      }}
    </Mutation>
  );
}

这篇关于如何使用React Apollo 2.1的Mutation组件在mount上运行变异?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆