React with GraphQL

GraphQL is a query language for APIs that allows you to request exactly the data you need, making it a powerful alternative to REST. It helps optimize network performance by reducing over-fetching and under-fetching of data, and it gives developers more control over the structure of the data they query.

Introduction to GraphQL and Why Use It with React

What is GraphQL?

GraphQL is an open-source data query language developed by Facebook. It allows clients to request only the data they need and get it in a structured and predictable format. Unlike REST, where multiple endpoints may be needed for different resources, GraphQL has a single endpoint where you can query for specific fields across multiple resources.

Why Use GraphQL with React?

When building React applications, especially those that interact with APIs, managing data can become challenging. GraphQL solves many of these challenges by offering:

  • Single endpoint: All requests are made to one endpoint, simplifying API calls.
  • Efficient data fetching: Only the data you ask for is returned, which reduces bandwidth.
  • Strong typing: GraphQL schemas define the types of data that can be queried, which helps prevent errors.
  • Real-time data: With subscriptions, you can enable real-time features in your React app, such as live chat or dashboards.

Setting Up a GraphQL Server

Before we connect GraphQL with React, let’s first set up a GraphQL server. We’ll use Apollo Server, a popular tool for building GraphQL APIs.

Installing Dependencies

To get started, install the required dependencies:

				
					npm init -y
npm install apollo-server graphql

				
			

Creating a Basic GraphQL Server

Here is a simple GraphQL server using Apollo Server:

				
					// index.js
const { ApolloServer, gql } = require('apollo-server');

// Define the GraphQL schema
const typeDefs = gql`
  type Query {
    hello: String
  }
`;

// Define the resolvers
const resolvers = {
  Query: {
    hello: () => 'Hello, GraphQL!',
  },
};

// Create the Apollo Server instance
const server = new ApolloServer({ typeDefs, resolvers });

// Start the server
server.listen().then(({ url }) => {
  console.log(`Server ready at ${url}`);
});
				
			

In this example:

  • typeDefs: Defines the GraphQL schema, which includes a query hello that returns a String.
  • resolvers: Functions that resolve the queries. In this case, hello returns the string "Hello, GraphQL!".

Output: When you run the server with node index.js, it starts at a URL (e.g., http://localhost:4000/) where you can query for hello:

				
					{
  hello
}

				
			

Response:

				
					{
  "data": {
    "hello": "Hello, GraphQL!"
  }
}

				
			

Integrating GraphQL with React

To connect GraphQL with a React application, we use Apollo Client. It simplifies the process of querying data from a GraphQL API and managing state in a React app.

Setting Up Apollo Client

First, we need to install Apollo Client and its dependencies:

				
					npm install @apollo/client graphql
				
			

Connecting Apollo Client to React

In a React application, we need to wrap our components with Apollo’s ApolloProvider to allow any child components to query data.

				
					// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { ApolloProvider, InMemoryCache, ApolloClient } from '@apollo/client';
import App from './App';

// Initialize Apollo Client
const client = new ApolloClient({
  uri: 'http://localhost:4000/', // GraphQL server URI
  cache: new InMemoryCache(),
});

ReactDOM.render(
  <ApolloProvider client={client}>
    <App />
  </ApolloProvider>,
  document.getElementById('root')
);

				
			

Explanation:

  • ApolloClient: Connects to our GraphQL server at http://localhost:4000/.
  • InMemoryCache: Caches query results, optimizing performance.
  • ApolloProvider: Wraps the entire app to provide GraphQL capabilities to all components.

Fetching Data with GraphQL Queries

Now that Apollo Client is set up, let’s fetch data using GraphQL queries in React.

Writing a Basic Query

To fetch data in a React component, we use the useQuery hook provided by Apollo.

				
					// src/App.js
import React from 'react';
import { useQuery, gql } from '@apollo/client';

// GraphQL query to fetch 'hello'
const HELLO_QUERY = gql`
  query GetHello {
    hello
  }
`;

const App = () => {
  const { loading, error, data } = useQuery(HELLO_QUERY);

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

  return <h1>{data.hello}</h1>;
};

export default App;

				
			

Explanation:

  • gql: Tagged template literal used to define the GraphQL query.
  • useQuery: A React hook that executes the query. It returns an object containing loading, error, and data.

Output: If the query is successful, the app will display:

				
					Hello, GraphQL!
				
			

Handling Variables in GraphQL Queries

GraphQL queries often require variables (parameters). You can pass variables to queries using Apollo Client.

Query with Variables

Let’s modify our GraphQL server to accept a variable for the hello query:

				
					// Server: index.js
const { ApolloServer, gql } = require('apollo-server');

const typeDefs = gql`
  type Query {
    hello(name: String!): String
  }
`;

const resolvers = {
  Query: {
    hello: (_, { name }) => `Hello, ${name}!`,
  },
};

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

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

				
			

Now, we need to modify our React app to pass a name variable in the query:

				
					// src/App.js
import React, { useState } from 'react';
import { useQuery, gql } from '@apollo/client';

const HELLO_QUERY = gql`
  query GetHello($name: String!) {
    hello(name: $name)
  }
`;

const App = () => {
  const [name, setName] = useState("John");
  const { loading, error, data } = useQuery(HELLO_QUERY, {
    variables: { name },
  });

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

  return (
    <div>
      <h1>{data.hello}</h1>
      <input
        type="text"
        value={name}
        onChange={(e) => setName(e.target.value)}
      />
    </div>
  );
};

export default App;

				
			

Explanation:

  • We added a name variable to the query and passed it using useQuery.
  • The input field allows users to change the name dynamically.

Output:

				
					Hello, John!
[Input Box]

				
			

Mutations in GraphQL

A mutation in GraphQL is used to create, update, or delete data. It’s similar to POST, PUT, DELETE in REST.

Basic Mutation Example

Let’s extend our server to handle a mutation that adds a user:

				
					const typeDefs = gql`
  type User {
    id: ID!
    name: String!
  }

  type Query {
    users: [User]
  }

  type Mutation {
    addUser(name: String!): User
  }
`;

const users = [];

const resolvers = {
  Query: {
    users: () => users,
  },
  Mutation: {
    addUser: (_, { name }) => {
      const newUser = { id: users.length + 1, name };
      users.push(newUser);
      return newUser;
    },
  },
};

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

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

				
			

Now, let’s modify the React app to execute this mutation:

				
					import React, { useState } from 'react';
import { useMutation, gql } from '@apollo/client';

const ADD_USER = gql`
  mutation AddUser($name: String!) {
    addUser(name: $name) {
      id
      name
    }
  }
`;

const App = () => {
  const [name, setName] = useState('');
  const [addUser, { data }] = useMutation(ADD_USER);

  return (
    <div>
      <input
        value={name}
        onChange={(e) => setName(e.target.value)}
        placeholder="Enter user name"
      />
      <button onClick={() => addUser({ variables: { name } })}>
        Add User
      </button>
      {data && <p>Added User: {data.addUser.name}</p>}
    </div>
  );
};

export default App;

				
			

Explanation:

  • useMutation: Executes the mutation when the button is clicked.
  • The data returned after the mutation is displayed on the screen.

Subscriptions for Real-Time Data

Subscriptions enable real-time communication between the server and the client. We can implement them using websockets in Apollo.

Using GraphQL with React offers tremendous flexibility and efficiency in data handling. By allowing you to fetch exactly what you need, GraphQL optimizes both frontend and backend performance. Apollo Client makes the integration seamless, enabling you to build powerful and scalable applications. Happy Coding!❤️

Table of Contents