如何从React Native调用GraphQL查询订阅

如何从React Native调用GraphQL查询订阅

下面是一个示例,展示如何从 React Native 应用程序调用 GraphQL查询、突变和订阅。 GraphQL 正在成为在现代 Web 和移动应用程序中使用 API 的新方式。 GraphQL 是 REST 的替代方案,自发布以来一直在稳步普及。 使用 REST 时,开发人员通常会整理来自一系列端点请求的数据,而 GraphQL 允许开发人员向服务器发送单个查询来描述确切的数据需求。 有关 GraphQL 的更多信息,您可以访问 GraphQL 官方网站

在此示例中,我们不会深入讨论 GraphQL,因为它本身就是一个很大的主题,我们将了解如何从React Native调用GraphQL查询订阅

Apollo 服务器和 Apollo 客户端

阿波罗服务器 是一个开源 GraphQL服务器,与任何 GraphQL 客户端兼容,包括 阿波罗客户端。 这是构建可以使用任何来源的数据的生产就绪、自记录的 GraphQL API 的最佳方式。

阿波罗客户端 帮助您以经济、可预测和声明的方式构建代码。 核心 @apollo/client 库提供与 React 的内置集成,并且更大的 Apollo 社区维护 其他流行视图层的集成。

调用 GraphQL 查询、变异和订阅

在进一步讨论之前,让我们先了解一下什么是 GraphQL查询、变异和订阅?

询问 用于获取/获取记录。 它就像任何 GET 请求一样,可以使用一些查询参数来过滤记录。

突变 用于创建/更新记录。 我们可以将其想象为 POST / PUT / PATCH / DELETE 请求。

订阅 保持与 GraphQL 服务器的活动连接(最常见的是通过 WebSocket)。 这使您的服务器能够随着时间的推移推送订阅结果的更新。 订阅对于实时通知客户有关后端数据的更改非常有用,例如创建新对象或更新重要字段。

示例说明

在此示例中,我们将有 3 个按钮可供调用

  1. 无负载的简单查询

  2. 通过将有效负载作为变量传递来动态查询有效负载

  3. 通过将有效负载作为变量传递来进行变异

我们还将订阅 GraphQL 订阅来创建记录,这意味着每当创建记录时,GraphQL 都会向我们实时接收的所有订阅者发布一条消息。

我希望在完成这个示例后,您能够正确理解如何调用 GraphQL 查询和突变以及如何从 React Native App 订阅 GraphQL 订阅。 如果您想添加一些观点,请随时在下面的评论中与我们分享。

让我们从例子开始。

GraphQL 服务器设置

对于此示例,您将需要 GraphQL 服务器来调用查询和突变,如果您有自己的 GraphQL 服务器,那么您可以忽略此部分,否则可以按照以下步骤设置虚拟 GraphQL 服务器。
1. 克隆仓库

git clone https://github.com/SnehalAgrawal/about-react-dummy-graphql-apis.git

2. 跳转到目录

cd about-react-dummy-graphql-apis

3.安装node_module

npm install

4. 运行 GraphQL 服务器

npm start

这将为您启动 GraphQL 服务器

ReactNativeCallGraphQLQueryMutationServer

启动 GraphQL 服务器后,您可以进入下一步创建 React Native 应用程序,该应用程序将从该 GraphQL 服务器订阅并调用查询和变更。

制作 React Native 应用程序

React Native 入门将帮助您更多地了解如何制作 React Native 项目。 我们将使用 React Native 命令行界面来制作我们的 React Native 应用程序。

如果您之前安装了全局的react-native-cli软件包,请将其删除,因为它可能会导致意外问题:

npm uninstall -g react-native-cli @react-native-community/cli

运行以下命令创建一个新的 React Native 项目

npx react-native init ProjectName

如果你想使用特定的 React Native 版本启动一个新项目,你可以使用 –version 参数:

npx react-native init ProjectName --version X.XX.X

注意如果上述命令失败,您可能使用的是旧版本 react-native 或者 react-native-cli 在您的电脑上全局安装。 尝试卸载 cli 并使用 npx 运行 cli。

这将在项目目录中创建一个带有名为 App.js 的索引文件的项目结构。

安装依赖项

要安装任何依赖项,请打开终端并使用以下命令跳转到项目中

cd ProjectName

如上所述,要从 React Native 应用程序调用 GraphQL 查询和突变,我们将使用 Apollo 客户端库。 要使用它安装 @apollo/clientgraphql

@阿波罗/客户端:这个软件包几乎包含设置 Apollo 客户端所需的所有内容。 它包括内存缓存、本地状态管理、错误处理和基于 React 的视图层。
图ql:该包提供了解析 GraphQL 查询的逻辑。

npm install @apollo/client graphql --save

由于订阅维护持久连接,因此它们无法使用 Apollo Client 用于查询和变更的默认 HTTP 传输。 相反,Apollo 客户端订阅最常通过社区维护的 WebSocket 进行通信 subscriptions-transport-ws 图书馆。 所以也安装它

npm install subscriptions-transport-ws --save

此命令会将所有依赖项复制到您的 node_module 目录中。 –save 是可选的,它只是更新 package.json 文件中的依赖项。

调用 GraphQL 查询和变异的代码

在任何代码编辑器中打开 App.js 并替换以下代码来调用 GraphQL Query、Mutation 并订阅 GraphQL 订阅。 如果您使用自己的 GraphQL 服务器,请检查 GraphQL URL。

应用程序.js

// How to Call GraphQL Query and Mutation from React Native
// https://aboutreact.com/react-native-call-graphql-query-mutation-subscribe/

// import React in our code
import React, {useEffect, useState} from 'react';

// import all the components we are going to use
import {
  SafeAreaView,
  StyleSheet,
  View,
  Text,
  TouchableOpacity,
} from 'react-native';

import {
  ApolloClient,
  InMemoryCache,
  ApolloProvider
} from '@apollo/client';
import {gql} from '@apollo/client';
import {WebSocketLink} from '@apollo/client/link/ws';

const App = () => {
  const (user, setUser) = useState({});

  // Connection for the subscription
  const wsLink = new WebSocketLink({
    uri: `ws://localhost:4000/graphql`,
    options: {
      reconnect: true,
    },
  });

  // Initialize Apollo Client
  const client = new ApolloClient({
    uri: 'http://localhost:4000/graphql',
    headers: {
      // Header(if any)
      authorization: 'a1b2c3d4-a1b2-a1b2c3d4e5f6',
    },
    cache: new InMemoryCache(),
    // link WebSocketLink subscription
    link: wsLink,
  });

  useEffect(() => {
    // Creating Suscription Observer
    let observer = client.subscribe({
      query: gql`
        subscription userAdded {
          userAdded {
            name
            age
            email
            address
            password
          }
        }
      `,
    });

    // Observer callback
    let subscriptionObj = observer.subscribe((result) => {
      console.log('Subscription data => ', result.data.userAdded);
      setUser(result.data.userAdded);
    });

    return () => {
      // Unsubscribe subscription
      console.log('Unsubscribed');
      subscriptionObj.unsubscribe();
    };
  }, ());

  const simpleQuery = async () => {
    // Calling Simple Graph Query
    const {data, error} = await client.query({
      query: gql`
        query users {
          users {
            name
            age
            email
            address
            password
          }
        }
      `,
    });
    // In case Error in Response
    if (error) {
      alert(`error + ${JSON.stringify(error)}`);
      console.log('error', JSON.stringify(error));
      return;
    }
    alert(`Got Record of ${data.users.length} Users`);
    console.log('data', JSON.stringify(data));
  };

  const dynamicQuery = async () => {
    // Calling Graph Query with variables
    const {data, error} = await client.query({
      query: gql`
        query user($email: String!) {
          user(email: $email) {
            name
            age
            email
            address
            password
          }
        }
      `,
      variables: {
        email: 'netus.et.malesuada@ornarelectusjusto.co.uk'
      },
    });
    // In case Error in Response
    if (error) {
      console.log('error', JSON.stringify(error));
      alert(`error + ${JSON.stringify(error)}`);
      return;
    }
    console.log('data', JSON.stringify(data.user));
    alert(`Response: ${JSON.stringify(data.user)}`);
  };

  const simpleMutation = async () => {
    // Calling Graph Mutation with variables
    const {data, error} = await client.mutate({
      mutation: gql`
        mutation createUser(
          $name: String!
          $email: String!
          $age: Int!
          $address: String!
          $password: String!
        ) {
          createUser(
            name: $name
            email: $email
            age: $age
            address: $address
            password: $password
          )
        }
      `,
      variables: {
        name: `New User ${Math.random()}`,
        //'newuser@gmail.com',
        email: `newuser${Math.random()}@gmail.com`,
        age: 30,
        address: 'Demo Address',
        password: '12345',
      },
    });
    // In case Error in Response
    if (error) {
      alert(`error => ${JSON.stringify(error)}`);
      console.log('error', JSON.stringify(error));
      return;
    }
    alert(`Response: ${JSON.stringify(data.createUser)}`);
    console.log('data', JSON.stringify(data.createUser));
  };

  return (
    <ApolloProvider client={client}>
      <SafeAreaView style={styles.container}>
        <View style={styles.container}>
          <Text style={styles.titleText}>
            How to Call GraphQL Query and Mutation from React Native
          </Text>
          <View style={styles.innerContainer}>
            <Text style={styles.textStyle}>
              Run Simple Query (Get All User)
            </Text>
            <TouchableOpacity
              activeOpacity={0.7}
              style={styles.buttonStyle}
              onPress={simpleQuery}>
              <Text style={styles.buttonTextStyle}>Get Data</Text>
            </TouchableOpacity>
          </View>
          <View style={styles.innerContainer}>
            <Text style={styles.textStyle}>
              Run Dynamic Query by passing payload as variable {'\n'}
              (Get Single User by Email)
            </Text>
            <TouchableOpacity
              activeOpacity={0.7}
              style={styles.buttonStyle}
              onPress={dynamicQuery}>
              <Text style={styles.buttonTextStyle}>Get Data</Text>
            </TouchableOpacity>
          </View>
          <View style={styles.innerContainer}>
            <Text style={styles.textStyle}>
              Run Mutation by passing payload as variable {'\n'}
              (Create User)
            </Text>
            <TouchableOpacity
              activeOpacity={0.7}
              style={styles.buttonStyle}
              onPress={simpleMutation}>
              <Text style={styles.buttonTextStyle}>Add User</Text>
            </TouchableOpacity>
          </View>
          <View style={styles.innerContainer}>
            <Text style={styles.textStyle}>
              Subscription Data {'\n'}
              (Subscribed for Successfull user Creation)
            </Text>
            <Text style={{textAlign: 'center'}}>
              Last Added User: {JSON.stringify(user)}
            </Text>
          </View>
        </View>
        <Text
          style={{
            fontSize: 16,
            textAlign: 'center',
            color: 'grey',
          }}>
          www.aboutreact.com
        </Text>
      </SafeAreaView>
    </ApolloProvider>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'white',
    padding: 10,
    textAlign: 'center',
  },
  innerContainer: {
    marginTop: 16,
    backgroundColor: '#f5f5f5',
    padding: 16,
    marginBottom: 10,
  },
  titleText: {
    fontSize: 22,
    textAlign: 'center',
    fontWeight: 'bold',
  },
  textStyle: {
    fontSize: 16,
    textAlign: 'center',
    marginBottom: 10,
  },
  buttonStyle: {
    justifyContent: 'center',
    padding: 10,
    backgroundColor: '#8ad24e',
  },
  buttonTextStyle: {
    color: '#fff',
    textAlign: 'center',
  },
});

export default App;

运行 React Native 应用程序

再次打开终端并使用跳转到您的项目。

cd ProjectName

1. 启动 Metro Bundler

首先,您需要启动 Metro,React Native 附带的 JavaScript 捆绑器。 要启动 Metro 捆绑程序,请运行以下命令

npx react-native start

一旦您启动 Metro Bundler,它将永远在您的终端上运行,直到您将其关闭。 让 Metro Bundler 在自己的终端中运行。 打开一个新终端并运行该应用程序。

2.启动React Native应用程序

在 Android 虚拟设备或真实调试设备上运行项目

npx react-native run-android

或在 iOS 模拟器上运行(仅限 macOS)

npx react-native run-ios

输出截图

这就是如何从 React Native 调用 GraphQL 查询和突变。 如果您有任何疑问或想分享有关该主题的内容,您可以在下面发表评论或在此处联系我们。 很快就会有更多帖子发布。

推荐:如何在Debian 12/11 Linux中安装Podman


发表评论