当前位置: 首页 > 面试题库 >

如何使用React Apollo 2.1的Mutation组件在挂载上运行突变?

廖永长
2023-03-14
问题内容

我们目前正在从Relay转移到React Apollo
2.1
,而我正在做的事情似乎很糟糕。

上下文: 只有在通过用户身份验证(通过API密钥)的情况下,才必须渲染某些组件,因此有一个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>;
      }}
    />
  );
}

如果身份验证成功,MyComponent将进行渲染。
Authentication在第一次渲染/安装时将身份验证突变发送到服务器,并相应地调用渲染道具。 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等效组件的区别在于仅渲染它即可发出请求。而且我想知道是否有一种方法可以将相同的机制应用于Mutation,这需要调用mutate函数作为render
prop的一部分。

上面代码片段的Relay等效功能完全可以实现React Apollo的Query功能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在装载时获取查询,同时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>
  );
}


 类似资料:
  • 问题内容: 我有一个从docker-compose.yml指向的Dockerfile。 我希望将docker-compose.yml中的卷挂载在Dockerfile中之前进行。 Dockerfile: docker-compose.yml 首先执行Dockerfile,然后从docker-compose挂载是完全有意义的,但是有一种解决方法。 我想保持Dockerfile通用,同时从compose

  • 我想在Docker上运行SonarQube。当我运行whiteout volume Persisted选项时,它与以下命令一起正常工作: 2019-07-07 06:42:41,143无法创建文件/opt/sonarqube/logs/es.log java.io.io.ioException:在java.base/java.io.unixfilesystem.createFileTraction

  • 我正在尝试运行Docker容器来分析Google Cloud Bucket中的数据。 我已经能够使用成功挂载存储桶,并且我测试了是否可以在存储桶中创建和删除文件之类的操作。 为了能够安装其他程序(并挂载bucket),我安装了Docker(并且没有使用Docker优化实例选项)。如果我在交互模式下运行Docker(不安装驱动器),它看起来工作正常。 但是,如果我尝试以交互模式运行Docker并安装

  • 如何使用智能电子和PIT测试Android应用程序? 使用Robolectic,您可以在JVM中运行Android测试。使用PIT,您可以显示行覆盖范围并进行突变测试。对我来说,使用Eclipse插件是可以的,但没有要求。 这就是我迄今为止所尝试的: 我有一个Android项目,我们称之为MyProject。 我现在想在JVM中使用Robolectic和PIT测试MyProject。因此,我创建了

  • 如何使用钩子(或任何其他钩子)来复制? 在传统的类组件中,我将执行以下操作: 使用hook: (完整示例:https://codesandbox.io/s/2oo7zqzx1n) 这不起作用,因为在中返回的“cleanup”函数捕获装载期间的道具,而不是卸载期间的道具状态。 如何在不运行函数体(或清除)的情况下对每个道具更改进行清理? 一个类似的问题并没有涉及获得最新道具的部分。 文件状态为: 如

  • 我正在使用https://react-pdf.org/的react-pdf包创建一个PDF生成器。将react-pdf组件转换为pdf的过程会阻塞主线程,因此我希望在一个单独的工作线程上转换它们。 我正在使用带有worker-loader的create-react-app来识别WebWorker文件。我很难找到将react组件导入Webworker并使用React-PDF提供的pdf(Compon