javascript - 如何使用 React Apollo 2.1 的 Mutation 组件在 mount 上运行突变?

标签 javascript reactjs apollo react-apollo apollo-client

我们目前正在从 Relay 移动至 React Apollo 2.1我正在做的事情似乎有问题。

上下文:某些组件必须仅在用户通过身份验证(通过 API key )时呈现,因此有一个 Authenticator 组件保护树的其余部分。

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, token }) => {
        if (error) return <div>{error.message}</div>;
        if (token) return <MyComponent token={token} />;
        return <div>Authenticating...</div>;
      }}
    />
  );
}

如果身份验证成功,将呈现 MyComponentAuthentication 在首次呈现/安装时将身份验证突变发送到服务器并调用 render prop因此。 Authentication.js 看起来是这样的:

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( ) 重新运行),但它应该如何使用?

好像是Query component equivalent不同之处在于简单地渲染它会发出请求。我想知道是否有一种方法可以将相同的机制应用于 Mutation,这需要调用 mutate 函数作为 render prop 的一部分。

上面代码片段的 Relay 等效项与 React Apollo 的 QueryMutation 上所做的完全相同:

// 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 都对如何使用查询和变更做出了一些假设。按照惯例,查询仅获取数据,而突变,嗯,突变数据。 Apollo 将这一范式更进一步,并假设突变会因某种行为而发生。因此,正如您观察到的那样,Query 在挂载时获取查询,而 Mutation 传递一个函数来实际获取突变。

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

我认为您的方法没有任何完全错误——假设 called 永远不会被重置,您的组件应该按预期运行。但是,作为替代方案,您可以创建一个简单的包装器组件以利用 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>
  );
}

关于javascript - 如何使用 React Apollo 2.1 的 Mutation 组件在 mount 上运行突变?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49456738/

相关文章:

Apollo 链接状态默认解析器不工作(@client 查询参数变量)

javascript - 如何调整窗口大小而不在加载页面上执行

javascript - 如何在每次鼠标悬停事件时更改单个 div 的颜色?

javascript - PreventDefault() 方法不阻止页面重新加载 ReactJS

reactjs - 处理主机应用程序中的模块联合失败

javascript - 测量文本宽度/高度而不渲染

javascript - 需要打勾的函数

javascript - 使用 typescript 的 create-react-app 将函数编译成非常奇怪的东西

java - 为什么 QoS = 1 时 MQTT 速度减慢这么多?

node.js - Apollo 查询缓存中的数据错误