如何使用GraphQL和Apollo构建一个宝可梦应用

news2024/11/16 0:40:20

宝可梦是一个由视频游戏、动画系列与电影、交换卡牌游戏以及其他相关媒体组成的日本媒体特许经营权。

在本文中,我们将使用一个宝可梦GraphQL API,该API提供有关不同宝可梦的数据。

我们将使用Apollo和GraphQL来处理数据获取,以及React来构建我们的前端应用程序。

如果您不了解这些技术,也不用担心,我将会在您阅读的过程中为您介绍基础知识。

(本文内容参考:java567.com)

先决条件

您的计算机上应该有以下内容以便跟着做:

  • Nodejs v18+
  • 一个代码编辑器
  • 一个网页浏览器

让我们创建我们的React应用程序。

React应用程序设置

要创建您的React应用程序,请转到您的终端,并使用命令提示符。打开您的命令提示符,并选择您喜欢创建React项目的位置。让我们选择桌面。

cd Desktop

上述命令将导航到您的桌面。

npm create vite@latest pokemon-app -- --template react

npm create vite@latest 将开始使用Vite构建一个新项目。但是,我们附加了我们项目的名称(pokemon-app)以及我们应用程序将使用的技术或框架(-- – template react)。

您可以设置另一个模板,如svelte、vanilla或vue,项目将使用该框架创建。在其官方网站上关于Vite的信息。

安装Vite之后,运行以下命令:

cd pokemon-app
npm install
npm run dev

我们将使用上述命令完成React设置。

运行第一个命令cd pokemon-app,以导航到pokeman-app文件夹。

运行code .来在您的代码编辑器中打开该文件夹。

在这里插入图片描述

如果弹出对话框要求信任文件的作者,请标记信任作者复选框。

打开您的代码编辑器终端。如果您在Windows上运行VSCode,则快捷键是`Ctrl + ``。

在终端中依次运行其他2个命令。

npm install
npm run dev

您的项目现在应该在浏览器中运行。

我们将使用GraphQL和Apollo来管理我们的数据获取。

如何使用GraphQL和Apollo

GraphQL是一种用于API的查询语言,也是用于使用现有数据执行查询的运行时。它允许您在应用程序中仅请求所需的数据,而不多余,从而使其非常高效和灵活。

Apollo是一个状态管理库,允许您使用GraphQL管理本地和远程数据。它可用于获取、缓存和修改应用程序数据,同时自动更新您的UI。

让我们安装您需要的包。

安装包

在您的终端中运行以下命令以安装Apollo客户端。

npm install @apollo/client

导航到您的main.jsx文件并导入以下内容:

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.jsx";
import {
  ApolloProvider,
  ApolloClient,
  InMemoryCache,
} from "@apollo/client";
import "./index.css";

您已经导入了React和ReactDOM用于DOM操作。

ApolloClient负责管理您应用程序的数据获取和状态管理。它负责将GraphQL查询和变异发送到GraphQL服务器并缓存结果。

ApolloProvider将用于包装您的React应用程序,以向所有组件提供Apollo客户端实例,以便您的应用程序可以通过Apollo客户端访问获取的数据。

InMemoryCache是一个缓存实现,用于将GraphQL查询的结果存储在内存中,以便高效地访问和检索。

您还导入了index.css来为您的应用程序设置样式。

如何创建Apollo客户端

const client = new ApolloClient({
  uri: "https://graphql-pokemon2.vercel.app/",
  cache: new InMemoryCache(),
});

以上代码使用了一些配置创建了ApolloClient的新实例:

  1. uri:这指定了您的GraphQL API端点的URL。这是您的Apollo客户端将发送GraphQL查询和变异的端点。
  2. cache:这配置了Apollo客户端的缓存实现,以使用内存缓存访问数据并存储GraphQL查询的结果,减少了从服务器重新获取数据的需要。

现在您可以将您的组件与ApolloProvider一起包装:

ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <ApolloProvider client={client}>
      <App />
    </ApolloProvider>
  </React.StrictMode>
);

请注意,client属性也被传递以提供您的应用程序ApolloClient的配置。

转到您的App.jsx组件并输入以下内容:

import React from "react";
import { PokemonsContainer } from "./components/PokemonsContainer";

export default function App() {
  return (
    <main>
      <PokemonsContainer />
    </main>
  );
}

您导入了React和将要创建的PokemonsContainer。PokemonsContainer组件被包装在main标签中,并将在组件粘贴到DOM中时呈现。

让我们在位于components文件夹中的文件中创建PokemonsContainer组件。即:

📂 src/components/PokemonsContainer.jsx

Pokemons Container组件

import React from "react";
import { useQuery } from "@apollo/client";
import { Pokemon } from "../components/Pokemon";
import { GET_POKEMONS } from "../graphql/get-pokemons";

来自@apollo/client的useQuery用于在Apollo应用程序中执行查询。为此,调用useQuery()并将GraphQL查询字符串作为参数传递。当您的组件渲染时,useQuery返回一个包含loading、error和data属性的对象,您可以使用这些属性来呈现您的UI。

导入了Pokemon组件以渲染Pokemon的用户界面,这将很快构建。

也导入了GET_POKEMONS。这将包含一个GraphQL查询。

在导入了上述函数之后,继续构建您的页面。

export function PokemonsContainer() {
  const { loading, error, data } = useQuery(GET_POKEMONS, {
    variables: { first: 5 },
  });

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error.message}</p>;

  const pokemons = data?.pokemons || [];
  return (
    <div className="container">
      {pokemons &&
        pokemons.map((pokemon) => (
          <Pokemon key={pokemon.id} pokemon={pokemon} />
        ))}
    </div>
  );
}

如前所述,useQuery返回一个包含loading、error和data属性的对象。它们在此处被解构,因此您可以在页面中访问它们。

请注意,我们为useQuery挂钩提供了一个配置选项(variables)。第二个参数也传递了{ variables: { first: 5 } }。variables选项是一个对象,其中包含我们要传递给GraphQL查询的所有变量。在这种情况下,我们传递了一个对象{ first: 5 }来指定我们要获取前五个Pokemons。

如果查询仍在加载中,则返回

Loading…

以通知用户,如果有错误,则返回

Error: {error.message}

创建了pokemons常量以保存数据对象的Pokemons属性的值。如果data.pokemons不可用,则pokemons常量将是一个空数组。

返回一个具有container类名的div,该div检查pokemons是否可用,并将数组映射到Pokemon组件。

让我们创建Pokemon组件:

📂src/components/Pokemon.jsx

宝可梦组件

import React from "react";

export function Pokemon({ pokemon }) {
  return (
    <div className="pokemon">
      <div className="pokemon__name">
        <p>{pokemon.name}</p>
      </div>
      <div className="pokemon__meta">
        <span>{pokemon.maxHP}</span>
        <span>{pokemon.maxCP}</span>
      </div>
      <div className="pokemon__image">
        <img src={pokemon.image} alt={pokemon.name} />
      </div>
      <div className="pokemon__attacks">
        {pokemon.attacks.special.slice(0, 3).map((attack) => (
          <span key={`${attack.name}-${attack.damage}`}>{attack.name}</span>
        ))}
      </div>
    </div>
  );
}

此处定义了宝可梦实例的结构,具有用于样式化的类名。将呈现名称、最大HP、最大CP、图像和攻击数组。

让我们创建GET_POKEMONS GraphQL查询。

📂src/graphql/get-pokemons

GraphQL 查询

import gql from "graphql-tag";

export const GET_POKEMONS = gql`
  query pokemons($first: Int!) {
    pokemons(first: $first) {
      id
      name
      image
      maxHP
      maxCP
      attacks {
        special {
          name
          damage
        }
      }
    }
  }
`;

您从graphql-tag导入了gql并创建了一个名为GET_POKEMONS的GraphQL查询。

将pokemons查询函数包装在字符串中,以便gql函数将它们解析为查询文档。

$first: Int! 表示您的查询期望一个名为first的变量,它是一个整数,! 符号表示该变量是必需的。

回想一下,我们在PokemonsContainer组件中创建了variables对象,在下面有这个对象。

 const { loading, error, data } = useQuery(GET_POKEMONS, {
   variables: { first: 5 },
 });

也声明了pokemons(first: f i r s t ) 。这里将 first)。这里将 first)。这里将first分配给了5(我们在上面的代码段中传入了9)。因此,数组将只包含5个对象。每个对象将包含id、name、image、maxHP、maxCP和攻击对象,该对象将包含特殊对象,其中包含name和damage。

GraphQL服务器可能包含更多属性,但只会返回上述列出的属性。这是GraphQL的一个很酷的功能——它只返回您请求的数据。

样式化我们的应用程序

您的index.css应该包含以下内容:

/* 重置
=========================================== */
html {
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
}

*,
*:before,
*:after {
  -webkit-box-sizing: inherit;
  box-sizing: inherit;
}

body {
  margin: 20px 0;
  padding: 0 20px;
  line-height: 1;
  font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
  color: #202020;
  background-color: #fbfbfb;
  font-smooth: always;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* 宝可梦应用程序
=========================================== */
.container {
  display: flex;
  max-width: 80%;
  margin: auto;
  height: 100vh;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
}

.container p {
  margin: 0;
}

.container .pokemon {
  width: 20%;
  background-color: #fff;
  background-clip: border-box;
  border: 1px solid rgba(0, 0, 0, 0.125);
  border-radius: 0.25rem;
  box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
  overflow: hidden;
  /* margin: 5px; */
}

.container .pokemon__name {
  background-color: #ecd018;
  text-align: center;
  padding: 10px;
}

.container .pokemon__name p {
  text-transform: uppercase;
  font-weight: bold;
  color: white;
  letter-spacing: 4px;
  text-shadow: 0px 1px 2px rgba(0, 0, 0, 0.4);
}

.container .pokemon__image {
  padding: 20px;
  min-height: 300px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.container .pokemon__image img {
  max-width: 100%;
  height: auto;
}

.container .pokemon__attacks {
  display: flex;
  padding-left: 10px;
  padding-right: 10px;
  justify-content: space-between;
}

.container .pokemon__attacks span {
  width: 32%;
  background-color: #f16820;
  border-radius: 3px;
  padding: 7px;
  font-weight: 700;
  color: #fff;
  padding-left: 10px;
  padding-right: 10px;
  font-size: 12px;
  margin-bottom: 10px;
  word-wrap: break-word;
  text-align: center;
  line-height: 15px;
}

.container .pokemon__meta {
  display: flex;
  justify-content: space-between;
  margin-top: 10px;
  padding: 0 10px;
}

.container .pokemon__meta span {
  color: white;
  text-shadow: 0px 1px 2px rgba(0, 0, 0, 0.4);
  background-color: #7bb7b7;
  font-weight: bold;
  margin: 0;
  padding: 5px 20px;
  border-radius: 5px;
}

一切正常,您应该在浏览器中看到以下内容:

显示了浏览器中五个宝可梦数据的图片

在这里插入图片描述

结论

就这样了。我希望您在这里找到了价值,学到了更多有关网络的知识。

如果您喜欢本文,并希望看到更多与JavaScript和Web开发相关的内容,别忘了点赞和关注。

谢谢,再见。

(本文内容参考:java567.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1574386.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据库之DCL操作(用户、访问权限。)

DCL英文全称是Data control language(数据控制语言)&#xff0c;用来管理数据库用户、控制数据库的访问权限。 1.管理用户 1.1查询用户 select * from mysql.user; 其中 Host代表当前用户访问的主机&#xff0c;如果为localhost&#xff0c;仅代表只能够在当前本机访问&…

git上传到本地仓库

摘要&#xff1a;本地初始化init仓库&#xff0c;进行pull和push&#xff1b;好处是便于利用存储设备进行git备份 git init --bare test.git 随便到一个空的目录下git clone 然后使用git上传 把git仓库删除之后再clone一次验证一下是否上传成功&#xff1a; 如果在ubantu上面没…

嵌入式面向对象学习 RT-Thread I/O 设备管理框架 设备驱动层 案例测试

嵌入式面向对象 RT-Thread I/O 设备管理框架 设备驱动层 注&#xff1a;本文介绍性内容转载于《RT-Thread记录&#xff08;十、全面认识 RT-Thread I/O 设备模型&#xff09;》 注&#xff1a; 本次使用的开发板 &#xff1a; ​ 兆易创新GD32F407VET6开发板 ​ 雅特力科技…

c++的学习之路:7、类和对象(3)

目录 一、初始化列表 二、static成员 三、友元 四、内部类 五、匿名对象 六、类和对象的思维导图 一、初始化列表 初始化列表&#xff1a;以一个冒号开始&#xff0c;接着是一个以逗号分隔的数据成员列表&#xff0c;每个"成员变量"后面跟一个放在括号中的初始…

求m和n的最大公约数(C语言)

一、运行结果&#xff1b; 二、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>int main() {//初始化变量值&#xff1b;int remainder 1;int m 0;int n 0;int middle 0;//提示用户&#xff1b;printf("请输入整数m和n的值&#xff…

辅助PC端教程

使用谷歌浏览器打开京东,并登录好账号进入到 https://home.jd.com/ ,在根据下面操作 更多工具 - 开发者工具,会有一个窗口打开,选择network,点击XHR

撸代码时,有哪些习惯一定要坚持?

我从2011年开始做单片机开发&#xff0c;一直保持以下撸代码的习惯。 1.做好代码版本管理 有些人&#xff0c;喜欢一个程序干到底&#xff0c;直到实现全部的产品功能&#xff0c;我以前做51单片机的项目就是这样。 如果功能比较多的产品&#xff0c;我不建议这样做&#xff0…

编译原理实验2(自上而下语法分析)

一、实验目的 给出 PL/0 文法规范&#xff0c;要求编写 PL/0 语言的语法分析程序。通过设计、编制、调试一个典型的自上而下语法分析程序&#xff0c;实现对词法分析程序所提供的单词序列进行语法检查和结构分析&#xff0c;进一步掌握常用的语法分析方法。选择有代表性的语法…

一款轻量、干净的 Vue 后台管理框架

开始之前 在开始介绍之前我想谈谈为什么要自己做一个后台管理&#xff0c;我知道很多人都用一些开源的后台管理项目&#xff0c;这些老前辈有很多亮点值得学习&#xff0c;但是存在的一些问题同样不可忽视&#xff0c;我认为很多开发者会被困扰(仅代表个人观点) 技术栈老旧不升…

面试(03)————多线程和线程池

一、多线程 1、什么是线程?线程和进程的区别? 2、创建线程有几种方式 &#xff1f; 3、Runnable 和 Callable 的区别&#xff1f; 4、如何启动一个新线程、调用 start 和 run 方法的区别&#xff1f; 5、线程有哪几种状态以及各种状态之间的转换&#xff1f; 6、线程…

Docker容器与虚拟化技术:OpenEuler 部署 ES 与 Kibana

目录 一、实验 1.环境 2.OpenEuler 部署 ES (EalasticSearch) 3.OpenEuler 部署 Kibana 4.部署 Elasticvue插件 5.使用cpolar内网穿透 6.使用Elasticvue 一、实验 1.环境 &#xff08;1&#xff09;主机 表1 主机 系统架构版本IP备注LinuxopenEuler22.03 LTS SP2 1…

flex布局align-items和align-content、justfiy-content的区别

justfiy-content&#xff1a;定义主轴的对齐方式align-items&#xff1a;定义交叉轴的对齐方式align-content&#xff1a;将flex子项作为一个整体起作用 只在两种情况下有效果&#xff1a; ①子项多行且flex容器高度固定 ②子项单行&#xff0c;flex容器高度固定且设置了fle…

Mac安装配置Appium

一、安装 nodejs 与 npm 安装方式与 windows 类似 &#xff0c;官网下载对应的 mac 版本的安装包&#xff0c;双击即可安装&#xff0c;无须配置环境变量。官方下载地址&#xff1a;https://nodejs.org/en/download/ 二、安装 appium Appium 分为两个版本&#xff0c;一个是…

HarmonyOS实战开发-屏幕属性(仅对系统应用开放)

介绍 本示例主要展示了屏幕管理相关的功能&#xff0c;使用ohos.display、ohos.screen接口&#xff0c;ohos.display接口提供获取默认display对象、获取所有display对象&#xff0c;开启监听、关闭监听功能&#xff1b;ohos.screen接口提供创建虚拟屏幕、销毁虚拟屏幕、扩展屏…

LeetCode-热题100:118. 杨辉三角

题目描述 给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 1: 输入: numRows 5 输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]] 示例 2: 输入: numRows 1 输出: [[1]]…

什么软件可以保密公司文件?

#天锐绿盾# 天锐绿盾是一款专为企业设计的文件加密与数据防泄密软件&#xff0c;旨在通过一系列高级安全功能来保护公司的敏感信息和重要文件不被未经授权的访问、窃取或泄露。 PC地址&#xff1a; https://isite.baidu.com/site/wjz012xr/2eae091d-1b97-4276-90bc-6757c5dfe…

蓝奏云直链获取在线解析网站源码

源码简介 蓝奏云直链获取在线解析网站源码 蓝奏云链接解析 本地API接口 支持有无密码和短期直链和永久直链&#xff0c;同时还可以显示文件名和大小。 这个解析器无需数据库即可搭建&#xff0c;API接口已经本地化&#xff0c;非常简单易用。 安装环境 php5.6 搭建教程 …

HTML - 你如何使H5页面禁止手动缩放

难度级别:初级及以上 提问概率:40% 我们知道,这道题其实是在考察meta标签的viewport属性,正常情况下设置viewport的代码为 <head><meta name="viewport" content="width=device-width,initial-scale=1.0" …

全网最详细的网络安全自学笔记

1.选择方向 首先是选择方向的问题&#xff0c;网络安全是一个很宽泛的专业&#xff0c;包含的方向特别多。比如 web安全&#xff0c;系统安全&#xff0c;无线安全&#xff0c;二进制安全&#xff0c;运维安全&#xff0c;渗透测试&#xff0c;软件安全&#xff0c;IOT安全&am…

【运输层】网络数据报协议 UDP

目录 1、UDP 的特点 2、UDP 的首部格式 UDP 只在 IP 协议之上增加了很少的一些功能&#xff0c;比如复用、分用以及差错检测等。 1、UDP 的特点 UDP是无连接的&#xff0c;即发送数据之前不需要建立连接&#xff0c;因此减少了开销和发送数据之前的时延。 UDP使用尽最大努力…