Skip to content

Apollo client server for graphQL API's

In this tutorial, we will get a brief introduction about apollo client server and how we use it with the graphQL API's in ReactJS.

GraphQL

GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data.

Send a GraphQL query to your API and get exactly what you need, nothing more and nothing less. GraphQL queries always return predictable results. Apps using GraphQL are fast and stable because they control the data they get, not the server.

GraphQL queries access not just the properties of one resource but also smoothly follow references between them. While typical REST APIs require loading from multiple URLs, GraphQL APIs get all the data your app needs in a single request.

Apollo Client

Apollo Client is a comprehensive and fully-featured JavaScript GraphQL client that enables you to communicate with a GraphQL server from a client-side application. It is a library that provides all the necessary functionality to interact with a GraphQL API, including handling queries and mutations, caching data, and managing state.

With Apollo Client, you can seamlessly integrate GraphQL with popular front-end frameworks and libraries like React, Angular, and Vue.js. It supports various features like real-time updates, server-side rendering, and error handling, among others, to help you build powerful and efficient applications.

One of the key advantages of using Apollo Client is its ability to manage the application's local state. It provides a simple way to manage the state in a central location and keep it in sync with the server's state. This makes it easier to build complex applications with a lot of data and interactivity.

Overall, Apollo Client is a popular and powerful tool for building GraphQL-based applications that can help simplify and optimize the data management and communication between client and server.

Implementation of Apollo Client in GraphQL

To set up Apollo Client with ReactJS, you will need to follow these steps:

  1. First we need a react project which we can create through these command.

    npx create-react-app application-name

  2. Install Apollo Client and its dependencies using NPM or Yarn:

    npm install @apollo/client graphql

    In this command there is two pacakges are installing apollo client and grpahQL.

    @apollo/client

    The package @apollo/client is used for managing state and making requests to a GraphQL API from a client-side application, such as a ReactJS application. It is a comprehensive and versatile GraphQL client library that provides features such as:

    • Querying and mutating data with GraphQL.
    • Managing local and remote data with a normalized cache.
    • Subscribing to real-time updates with GraphQL subscriptions.
    • Handling errors and retrying failed requests.
    • Customizing requests and responses with middleware.

    The @apollo/client package is designed to be easy to use and flexible, allowing developers to integrate it with a wide range of frontend frameworks and libraries. By using @apollo/client, developers can easily build powerful and efficient client-side applications that communicate with a GraphQL API.

    graphql

    The graphql package is used for working with GraphQL, a query language for APIs that provides a more efficient, powerful, and flexible alternative to REST. It provides a set of tools and utilities for working with GraphQL. The graphql package is used in both client-side and server-side applications to work with GraphQL. In server-side applications, it is used to define the GraphQL schema and resolvers, and to parse and validate incoming GraphQL queries. In client-side applications, it is used to construct and send GraphQL queries to a GraphQL server.

  3. Initialize ApolloClient with reactJS.

    . Import ApolloClient, InMemoryCache, and HttpLink from @apollo/client:.

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

    . Create a new instance of ApolloClient:

      const client = 0new ApolloClient({
          uri: '<your GraphQL API endpoint>',
          cache: new InMemoryCache(),
      });
    
      uri specifies the URL of our GraphQL server.
      cache is an instance of InMemoryCache, which Apollo Client uses to cache query results after fetching them
    

    . Wrap your React application with the ApolloProvider component, passing the client as a prop:

    <ApolloProvider client={client}>
        <App />
    </ApolloProvider>
    

    Now the setup is completed.

    Now, this is how we can fetch data from GraphQL API:

    For fetching the data from the graphQL server we have two concept: 1. Querry 2. Mutation

    Querry

    In Apollo Client, a query is a GraphQL operation that is sent to a GraphQL server to fetch data.

    Queries are defined using the GraphQL query language, and they specify the data that is to be fetched from the server. The data returned by a query is typically structured in the same shape as the query itself, with the fields and their values matching the corresponding fields in the response.

    Apollo Client provides a powerful API for managing queries, including the ability to define queries using template literals, to cache query results locally, to handle errors and loading states, and to automatically update data when it changes on the server using subscriptions.

    The useQuery hook is used in Apollo Client to fetch data from a GraphQL server using a GraphQL query. It is a React hook that provides a declarative way of fetching data and updating the UI in response to changes in the data.

    Here's how useQuery works:

    1. Define a GraphQL query using the gql function:

      import { gql } from '@apollo/client';
      
      const GET_USERS = gql`
      query {
          users {
              id
              name
              email
              address
          }
      }`;
      

      Here, GET_USERS is a GraphQL query that fetches a list of users.

      In this query, we're asking the server to fetch information about a movie with the ID of 123. We want to know the movie's title, release date, and the names and ages of its actors.

      We can also send the query params in the query, suppose i want only the data of the user which id is 123, and i only need user's name and email so this is how we can get that data from the server.

      query {
          users(id: 123) {
              name
              email
          }
      }
      

      Note that the structure of the query matches the shape of the data we expect to receive from the server. This is one of the key features of GraphQL, which allows clients to request only the data they need and receive it in a predictable and consistent format.

    2. Call the useQuery hook with the GraphQL query and any additional options:

      import { useQuery } from '@apollo/client';
      
      function UserList() {
          const { loading, error, data } = useQuery(GET_USERS);
      
          if (loading) return <p>Loading...</p>;
          if (error) return `Error! ${error}`;
      
          return (
              <ul>
              {data.users.map(user => (
                  <li key={user.id}>
                  {user.name} ({user.email})
                  </li>
              ))}
              </ul>
          );
      }
      

    In this example, we're using the useQuery hook to execute the users and fetch all the data about a user and in another example we are fetching the data with a specific ID. We're also handling loading and error states, and rendering the users details if the data is successfully fetched.

    Mutation

    In Apollo Client, a mutation is a way to modify data on a GraphQL server. Mutations are used to create, update, or delete data in a GraphQL API. A mutation is similar to a query in that it specifies a set of fields to be returned, but it also includes a set of operations to be performed on the server.

    In GraphQL, mutations are defined in the schema using the mutation keyword. Here's an example of a simple GraphQL mutation that adds a new user to a database.

    mutation AddUser($name: String!, $email: String!) {
        addUser(name: $name, email: $email) {
            id
            name
            email
        }
    }
    

    In this mutation, we define a new operation called AddUser, which takes two arguments: name and email, both of which are of type String. The addUser operation is defined in the server's schema and performs the actual operation of adding a new user to the database.

    In Apollo Client, we use the useMutation hook to execute a mutation against a GraphQL server. The useMutation hook returns a function that we can call to execute the mutation, along with a set of properties that we can use to track the status of the mutation (e.g. loading, error, and data).

    Here's an example of how to use useMutation in a React component to add a new user to a database:

    import { useMutation } from '@apollo/client';
    import { ADD_USER } from './mutations';
    
    function AddUserForm() {
        const [addUser, { loading, error, data }] = useMutation(ADD_USER);
    
        const handleSubmit = event => {
            event.preventDefault();
    
            const name = event.target.elements.name.value;
            const email = event.target.elements.email.value;
    
            addUser({ variables: { name, email } });
        };
    
        if (loading) return <p>Loading...</p>;
        if (error) return <p>Error :(</p>;
    
        return (
            <form onSubmit={handleSubmit}>
            <label>
                Name:
                <input type="text" name="name" />
            </label>
            <label>
                Email:
                <input type="email" name="email" />
            </label>
            <button type="submit">Add User</button>
            </form>
        );
    }
    

    In this example, we define a new component called AddUserForm that includes a form with two fields for entering the user's name and email address. We use the useMutation hook to define a new mutation called addUser, which we call when the user submits the form. The variables object that we pass to addUser contains the values of the name and email fields. Finally, we use the loading and error properties returned by useMutation to display a loading indicator or an error message, as appropriate.

    For delete a record

    To use a delete operation in a mutation using Apollo Client, you need to define the mutation in your GraphQL schema and then create a mutation in your Apollo Client code that calls the delete operation.

    Here is an example of a GraphQL mutation that deletes a user:

    mutation DeleteUser($userId: ID!) {
        deleteUser(id: $userId) {
            id
        }
    }
    

    In this mutation, we define an operation called DeleteUser that takes an argument called userId, which is of type ID!. The deleteUser operation is defined in the server's schema and performs the actual operation of deleting the user with the specified ID.

    To use this mutation in Apollo Client, you can use the useMutation hook, like this:

    import { useMutation } from '@apollo/client';
    import { DELETE_USER } from './mutations';
    
    function DeleteUserButton({ userId }) {
        const [deleteUser, { loading, error }] = useMutation(DELETE_USER);
    
        const handleDeleteUser = () => {
            deleteUser({ variables: { userId } });
        };
    
        if (loading) return <p>Loading...</p>;
        if (error) return <p>Error :(</p>;
    
        return (
            <button onClick={handleDeleteUser}>Delete User</button>
        );
    }
    

    In this example, we define a component called DeleteUserButton that displays a button for deleting a user. We use the useMutation hook to define a mutation called deleteUser, which we call when the user clicks the button. The variables object that we pass to deleteUser contains the ID of the user to be deleted. Finally, we use the loading and error properties returned by useMutation to display a loading indicator or an error message, as appropriate.

    Note that in the mutation definition, we have specified the id field to be returned after the user is deleted. You can modify this to return any fields that you need from the deleted object.

    We can also update the records as the same as above examples.

    Note:- Just remember that the name of the operation has to match the name of the query/mutation definition in your GraphQL schema on the server side. If you're not in control of the server-side schema, make sure to check the documentation or ask the API provider what the correct name is for the query/mutation you're trying to use.

    For file upload into the server.

    Apollo Client doesn't support a file upload feature out of the box. If you'd like to enable file upload capabilities, you will have to set Apollo Client up manually with a 3rd party package

    First, install the package using npm:-

    npm install apollo-upload-client
    
    Then, import the createUploadLink function from the package:
    
        import { createUploadLink } from 'apollo-upload-client';
    
    Next, create a new instance of createUploadLink and pass it as an argument to the ApolloClient constructor:
    
        import { ApolloClient, InMemoryCache } from '@apollo/client';
    
        const client = new ApolloClient({
            cache: new InMemoryCache(),
            link: createUploadLink(
                {
                    uri: 'https://flyby-gateway.herokuapp.com/' //uri is the url of server
                }
            ),
        });
    
    Now you can use file uploads in your GraphQL mutations. Define a mutation that accepts a file input:
    
        mutation UploadFile($file: Upload!) {
            uploadFile(file: $file) {
                id
                filename
                mimetype
                encoding
            }
        }
    
    And use the useMutation hook from @apollo/client to send the file data to the server:
    
        import { useMutation } from '@apollo/client';
    
        const [uploadFile] = useMutation(UPLOAD_FILE);
    
        const handleFileUpload = async (e) => {
            const file = e.target.files[0];
            const { data } = await uploadFile({ variables: { file } });
            console.log(data.uploadFile.id);
        };
    
        return (
            <div>
                <input type="file" onChange={handleFileUpload} />
            </div>
        );
    
    With apollo-upload-client, the file data is automatically encoded as a FormData object and sent to the server as a multipart/form-data request. The createUploadLink function takes care of adding the necessary headers and formatting the request data correctly.
    
    Note that apollo-upload-client only works with Apollo Client version 3 or later. If you are using an earlier version of Apollo Client, you may need to use a different package or implement file uploads manually.