」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 透過 REST API 上的 GraphQL 增強 React 應用程式

透過 REST API 上的 GraphQL 增強 React 應用程式

發佈於2024-11-07
瀏覽:913

In the rapidly changing world of web development, optimizing and scaling applications is always an issue. React.js had an extraordinary success for frontend development as a tool, that provides a robust way to create user interfaces. But it gets complicated with growing applications, especially when it comes to multiple REST API endpoints. Concerns such as over-fetching, where excessive data than required can be a source of performance bottleneck and a poor user experience.

Among the solutions to these challenges is adopting the use of GraphQL with React applications. If your backend has multiple REST endpoints, then introducing a GraphQL layer that internally calls your REST API endpoints can enhance your application from overfetching and streamline your frontend application. In this article, you will find how to use it, the advantages and disadvantages of this approach, various challenges; and how to address them. We will also dive deeper into some practical examples of how GraphQL can help you improve the ways you work with your data.

Overfetching in REST APIs

In REST APIs, Over-fetching occurs when the amount of data that the API delivers to the client is more than what the client requires. This is a common problem with REST APIs, which often returns a fixed Object or Response Schema. To better understand this problem let us consider an example.

Consider a user profile page where the it is only required to show the user’s name and email. With a typical REST API, fetching the user data might look like this:

fetch('/api/users/1')
  .then(response => response.json())
  .then(user => {
    // Use the user's name and profilePicture in the UI
  });

The API response will include unnecessary data:

{
  "id": 1,
  "name": "John Doe",
  "profilePicture": "/images/john.jpg",
  "email": "[email protected]",
  "address": "123 Denver St",
  "phone": "111-555-1234",
  "preferences": {
    "newsletter": true,
    "notifications": true
  },
  // ...more details
}

Although the application only requires the name and email fields of the user, the API returns the whole user object. This additional data often increases the payload size, take more bandwidth and can eventually slow down the application when used on a device with limited resources or a slow network connection.

GraphQL as a Solution

GraphQL addresses the overfetching problem by allowing clients to request exactly the data they need. By integrating a GraphQL server into your application, you can create a flexible and efficient data-fetching layer that communicates with your existing REST APIs.

How It Works

  1. GraphQL Server Setup: You introduce a GraphQL server that serves as an intermediary between your React frontend and the REST APIs.
  2. Schema Definition: You define a GraphQL schema that specifies the data types and queries your frontend requires.
  3. Resolvers Implementation: You implement resolvers in the GraphQL server that fetch data from the REST APIs and return only the necessary fields.
  4. Frontend Integration: You update your React application to use GraphQL queries instead of direct REST API calls.

This approach allows you to optimize data fetching without overhauling your existing backend infrastructure.

Implementing GraphQL in a React Application

Let’s look at how to set up a GraphQL server and integrate it into a React application.

Install Dependencies:

npm install apollo-server graphql axios

Define the Schema

Create a file called schema.js:

const { gql } = require('apollo-server');

const typeDefs = gql`
  type User {
    id: ID!
    name: String
    email: String  // Ensure this matches exactly with the frontend query
  }

  type Query {
    user(id: ID!): User
  }
`;

module.exports = typeDefs;

This schema defines a User type and a user query that fetches a user by ID.

Implement Resolvers

Create a file called resolvers.js:

const resolvers = {
  Query: {
    user: async (_, { id }) => {
      try {
        const response = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`);
        const user = await response.json();

        return {
          id: user.id,
          name: user.name,
          email: user.email,  // Return email instead of profilePicture
        };
      } catch (error) {
        throw new Error(`Failed to fetch user: ${error.message}`);
      }
    },
  },
};

module.exports = resolvers;

The resolver for the user query fetches data from the REST API and returns only the required fields.

We will use https://jsonplaceholder.typicode.com/for our fake REST API.

Set Up the Server

Create a server.js file:

const { ApolloServer } = require('apollo-server');
const typeDefs = require('./schema');
const resolvers = require('./resolvers');

const server = new ApolloServer({
  typeDefs,
  resolvers,
});

server.listen({ port: 4000 }).then(({ url }) => {
  console.log(`GraphQL Server ready at ${url}`);
});

Start the server:

node server.js

Your GraphQL server is live at http://localhost:4000/graphql and if you query your server, it will take you to this page.

Enhancing React Applications with GraphQL Over REST APIs

Integrating with the React Application

We will now change the React application to use the GraphQL API.

Install Apollo Client

npm install @apollo/client graphql

Configure Apollo Client

import { ApolloClient, InMemoryCache } from '@apollo/client';

const client = new ApolloClient({
  uri: 'http://localhost:4000', 
  cache: new InMemoryCache(),
});

Write the GraphQL Query

const GET_USER = gql`
  query GetUser($id: ID!) {
    user(id: $id) {
      id
      name
      email
    }
  }
`;

Now integrate the above pieces of codes with your react app. Here is a simple react app below which lets a user select the userId and displays the information:

import { useState } from 'react';
import { ApolloClient, InMemoryCache, ApolloProvider, gql, useQuery } from '@apollo/client';
import './App.css';  // Link to the updated CSS

const client = new ApolloClient({
  uri: 'http://localhost:4000',  // Ensure this is the correct URL for your GraphQL server
  cache: new InMemoryCache(),
});

const GET_USER = gql`
  query GetUser($id: ID!) {
    user(id: $id) {
      id
      name
      email
    }
  }
`;

const User = ({ userId }) => {
  const { loading, error, data } = useQuery(GET_USER, {
    variables: { id: userId },
  });

  if (loading) return 

Loading...

; if (error) return

Error: {error.message}

; return (

{data.user.name}

Email: {data.user.email}

); }; const App = () => { const [selectedUserId, setSelectedUserId] = useState("1"); return (

GraphQL User Lookup

); }; export default App;

Result:

Simple User

Enhancing React Applications with GraphQL Over REST APIs

Working with Multiple Endpoints

Imagine a scenario where you need to retrieve a specific user’s posts, along with the individual comments on each post. Instead of making three separate API calls from your frontend React app and dealing with unnecessary data, you can streamline the process with GraphQL. By defining a schema and crafting a GraphQL query, you can request only the exact data your UI requires, all in one efficient request.

We need to fetch user data, their posts, and comments for each post from the different endpoints. We’ll use fetch to gather data from the multiple endpoints and return it via GraphQL.

Update Resolvers

const fetch = require('node-fetch');

const resolvers = {
  Query: {
    user: async (_, { id }) => {
      try {
        // fetch user
        const userResponse = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`);
        const user = await userResponse.json();

        // fetch posts for a user
        const postsResponse = await fetch(`https://jsonplaceholder.typicode.com/posts?userId=${id}`);
        const posts = await postsResponse.json();

        // fetch comments for a post
        const postsWithComments = await Promise.all(
          posts.map(async (post) => {
            const commentsResponse = await fetch(`https://jsonplaceholder.typicode.com/comments?postId=${post.id}`);
            const comments = await commentsResponse.json();
            return { ...post, comments };
          })
        );

        return {
          id: user.id,
          name: user.name,
          email: user.email,
          posts: postsWithComments,
        };
      } catch (error) {
        throw new Error(`Failed to fetch user data: ${error.message}`);
      }
    },
  },
};

module.exports = resolvers;

Update GraphQL Schema

const { gql } = require('apollo-server');

const typeDefs = gql`
  type Comment {
    id: ID!
    name: String
    email: String
    body: String
  }

  type Post {
    id: ID!
    title: String
    body: String
    comments: [Comment]
  }

  type User {
    id: ID!
    name: String
    email: String
    posts: [Post]
  }

  type Query {
    user(id: ID!): User
  }
`;

module.exports = typeDefs;

Server setup in server.js remains same. Once we update the React.js code, we get the below output:

Detailed User

Enhancing React Applications with GraphQL Over REST APIs

Benefits of This Approach

Integrating GraphQL into your React application provides several advantages:

Eliminating Overfetching

A key feature of GraphQL is that it only fetches exactly what you request. The server only returns the requested fields and ensures that the amount of data transferred over the network is reduced by serving only what the query demands and thus improving performance.

Simplifying Frontend Code

GraphQL enables you to get the needful information in a single query regardless of their origin. Internally it could be making 3 API calls to get the information. This helps to simplify your frontend code because now you don’t need to orchestrate different async requests and combine their results.

Improving Developer’s Experience

A strong typing and schema introspection offer better tooling and error checking than in the traditional API implementation. Further to that, there are interactive environments where developers can build and test queries, including GraphiQL or Apollo Explorer.

Addressing Complexities and Challenges

This approach has some advantages but it also introduces some challenges that have to be managed.

Additional Backend Layer

The introduction of the GraphQL server creates an extra layer in your backend architecture and if not managed properly, it becomes a single point of failure.

Solution: Pay attention to error handling and monitoring. Containerization and orchestration tools like Docker and Kubernetes can help manage scalability and reliability.

Potential Performance Overhead

The GraphQL server may make multiple REST API calls to resolve a single query, which can introduce latency and overhead to the system.

Solution: Cache the results to avoid making several calls to the API. There exist some tools such as DataLoader which can handle the process of batching and caching of requests.

Conclusion

"Simplicity is the ultimate sophistication" — Leonardo da Vinci

Integrating GraphQL into your React application is more than just a performance optimization — it’s a strategic move towards building more maintainable, scalable, and efficient applications. By addressing overfetching and simplifying data management, you not only enhance the user experience but also empower your development team with better tools and practices.

While the introduction of a GraphQL layer comes with its own set of challenges, the benefits often outweigh the complexities. By carefully planning your implementation, optimizing your resolvers, and securing your endpoints, you can mitigate potential drawbacks. Moreover, the flexibility that GraphQL offers can future-proof your application as it grows and evolves.

Embracing GraphQL doesn’t mean abandoning your existing REST APIs. Instead, it allows you to leverage their strengths while providing a more efficient and flexible data access layer for your frontend applications. This hybrid approach combines the reliability of REST with the agility of GraphQL, giving you the best of both worlds.

If you’re ready to take your React application to the next level, consider integrating GraphQL into your data fetching strategy. The journey might present challenges, but the rewards — a smoother development process, happier developers, and satisfied users — make it a worthwhile endeavor.

Full Code Available

You can find the full code for this implementation on my GitHub repository: GitHub Link.

版本聲明 本文轉載於:https://dev.to/shreyam_duttagupta/enhancing-react-applications-with-graphql-over-rest-apis-91p?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • 解決 CORS 問題的方法
    解決 CORS 問題的方法
    要解决 CORS 问题,您需要在 Web 服务器(如 Apache 或 Nginx)、后端(如 Django、Go 或 Node.js)中添加适当的标头,或在前端框架(如 React 或 Next.js)中。以下是每个平台的步骤: 1. 网络服务器 阿帕奇 您可以在 ...
    程式設計 發佈於2024-11-07
  • 記憶體對齊如何影響 C 結構的大小?
    記憶體對齊如何影響 C 結構的大小?
    C 結構中的記憶體對齊使用 C 結構時,理解記憶體對齊至關重要。記憶體對齊是指將資料在記憶體中放置在特定的邊界處。在 32 位元機器上,記憶體通常按 4 位元組邊界對齊。 結構的記憶體對齊考慮以下結構:typedef struct { unsigned short v1; unsig...
    程式設計 發佈於2024-11-07
  • 受頂級旅遊景點啟發建構創新項目:令人難忘的旅遊體驗開發人員指南
    受頂級旅遊景點啟發建構創新項目:令人難忘的旅遊體驗開發人員指南
    作為開發商,我們經常從周圍的世界中汲取靈感——還有什麼比令人難以置信的旅遊景點更好的來源呢?無論您是在開發旅行應用程式、沉浸式體驗還是基於位置的服務,了解目的地的脫穎而出都是關鍵。看看這份關於阿爾巴尼亞最佳旅遊景點的終極指南,為您的下一個創意項目提供動力,並了解這些地標如何在現實世界和數位世界中塑造...
    程式設計 發佈於2024-11-07
  • 如何使用 std::locale 在 C++ 中使用逗號格式化數字?
    如何使用 std::locale 在 C++ 中使用逗號格式化數字?
    在C 中用逗號格式化數字在C 中,std::locale 類別提供了一種依賴於區域設定的方式用逗號格式化數字.std::locale 與std::stringstream要將數字格式化為帶逗號的字串,可以將std::locale 與std::stringstream 一起使用如下:#include ...
    程式設計 發佈於2024-11-07
  • 如何避免在 Python 中列印素數序列中的奇數?
    如何避免在 Python 中列印素數序列中的奇數?
    如何在 Python 中列印素數序列許多程式設計師都在努力創建一個在 Python 中準確列印素數的函數。一個常見的問題是列印奇數列表。要解決這個問題,必須徹底了解素數屬性並修改程式碼。 質數只能被 1 和它們本身整除。因此,改進的程式碼檢查從 2 到數字的平方根(如果數字較小,則為數字本身)範圍內...
    程式設計 發佈於2024-11-07
  • 如何在 Pygame 中向滑鼠方向發射子彈?
    如何在 Pygame 中向滑鼠方向發射子彈?
    如何在 Pygame 中朝滑鼠方向發射子彈在 Pygame 中,可以創建一顆朝滑鼠方向發射的子彈。為此,需要建立一個代表子彈的類,並根據滑鼠位置設定其初始位置和方向。 子彈的類別首先,為項目符號建立一個類別。該類別應包含子彈的位置、大小和表面的屬性。表面就是將在螢幕上渲染的內容。 import py...
    程式設計 發佈於2024-11-07
  • 優化效能的 GG 編碼技巧:加快程式碼速度
    優化效能的 GG 編碼技巧:加快程式碼速度
    在软件开发领域,优化代码性能对于交付用户喜爱的快速响应的应用程序至关重要。无论您从事前端还是后端工作,学习如何编写高效的代码都是至关重要的。在本文中,我们将探讨各种性能优化技术,例如降低时间复杂度、缓存、延迟加载和并行性。我们还将深入探讨如何分析和优化前端和后端代码。让我们开始提高代码的速度和效率!...
    程式設計 發佈於2024-11-07
  • 如何使用 PHP 的 strtotime() 函數找出一週中特定一天的日期?
    如何使用 PHP 的 strtotime() 函數找出一週中特定一天的日期?
    確定一周中指定日期(星期一、星期二等)的日期如果您需要確定日期戳一周中的特定一天,例如星期一、星期二或任何其他工作日,可以使用strtotime() 函數。當指定日期在本週內尚未出現時,此函數特別有用。 例如,要獲取下週二的日期戳,只需使用以下代碼:strtotime('next tuesday')...
    程式設計 發佈於2024-11-07
  • 使用 Socket.io 和 Redis 建置和部署聊天應用程式。
    使用 Socket.io 和 Redis 建置和部署聊天應用程式。
    在本教程中,我们将使用 Web 套接字构建一个聊天应用程序。当您想要构建需要实时传输数据的应用程序时,Web 套接字非常有用。 在本教程结束时,您将能够设置自己的套接字服务器、实时发送和接收消息、在 Redis 中存储数据以及在渲染和 google cloud run 上部署您的应用程序。 ...
    程式設計 發佈於2024-11-07
  • SQL 連結內部
    SQL 連結內部
    SQL 连接是查询数据库的基础,它允许用户根据指定条件组合多个表中的数据。连接分为两种主要类型:逻辑连接和物理连接。逻辑联接代表组合表中数据的概念方式,而物理联接是指这些联接在数据库系统(例如 RDS(关系数据库服务)或其他 SQL 服务器)中的实际实现。在今天的博文中,我们将揭开 SQL 连接的神...
    程式設計 發佈於2024-11-07
  • 你該知道的 Javascript 特性
    你該知道的 Javascript 特性
    在本文中,我們將探討如何在嘗試存取可能是未定義或null 的資料時防止錯誤,並且我們將介紹您可以使用的方法用於在必要時有效管理資料。 透過可選連結進行安全訪問 在 JavaScript 中,當您嘗試存取嵌套物件中的值或函數時,如果結果為 undefined,您的程式碼可能會引發錯誤...
    程式設計 發佈於2024-11-07
  • JavaScript 中的 Promise:理解、處理和掌握非同步程式碼
    JavaScript 中的 Promise:理解、處理和掌握非同步程式碼
    简介 我曾经是一名 Java 开发人员,我记得第一次接触 JavaScript 中的 Promise 时。尽管这个概念看起来很简单,但我仍然无法完全理解 Promise 是如何工作的。当我开始在项目中使用它们并了解它们解决的案例时,情况发生了变化。然后灵光乍现的时刻到来了,一切都变...
    程式設計 發佈於2024-11-07
  • 如何將金鑰整合到 Java Spring Boot 中
    如何將金鑰整合到 Java Spring Boot 中
    Java Spring Boot 中的密钥简介 密钥提供了一种现代、安全的方式来验证用户身份,而无需依赖传统密码。在本指南中,我们将引导您使用 Thymeleaf 作为模板引擎将密钥集成到 Java Spring Boot 应用程序中。 我们将利用 Corbado 的密钥优先 UI...
    程式設計 發佈於2024-11-07
  • 馬裡奧·羅伯托·羅哈斯·埃斯皮諾擔任危地馬拉前環境部長的影響
    馬裡奧·羅伯托·羅哈斯·埃斯皮諾擔任危地馬拉前環境部長的影響
    作為危地馬拉前環境部長,馬裡奧·羅伯托·羅哈斯·埃斯皮諾在執行環境政策方面發揮了至關重要的作用,為該國的可持續發展做出了貢獻。他作為該部門領導的管理留下了重要的遺產,特別是在環境立法和保護項目方面。在本文中,我們探討了他的影響以及他在任期內推行的主要政策。 主要環境政策 在擔任部長...
    程式設計 發佈於2024-11-07
  • 如何追蹤和存取類別的所有實例以進行資料收集?
    如何追蹤和存取類別的所有實例以進行資料收集?
    追蹤資料收集的類別實例假設您正在接近程式末尾,並且需要從多個變數中提取特定變數來填充字典的類別的實例。當處理包含需要聚合或分析的基本資料的物件時,可能會出現此任務。 為了說明這個問題,請考慮這個簡化的類別結構:class Foo(): def __init__(self): ...
    程式設計 發佈於2024-11-07

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3