Select Page

How To Implement magneto GraphQl Apis with NextJS

vishal.handa658
Published: February 13, 2023

Initially we work on the implementation of useForm() Hook in NextJS | React. Now In this we work on implementation of Magento GraphQl Api’s with NextJS. But before that we need to setup Apollo Client for managing the GraphQl Api’s.
The Apollo Client is a state management client which allow user to manage local and remote data with GraphQl and you can use it to cache, fetch, and also modify application data.

Step 1 : Install the Apollo client

Inside of your terminal run this command to install Apollo Client.

npm install @apollo/client graphql

This will add the both Apollo Client and GraphQl, which we’ll need to implement the GraphQl Query.

Step 2 : Set up the Apollo client in NextJS .

Create a file “lib/apolloClient.js” for storing the Apollo Client configuration. In which we’ll be creating a basic function that returns an Apollo Client instance.

 import { useMemo } from "react";
 import { ApolloClient, HttpLink, InMemoryCache } from "@apollo/client";
 let apolloClient;
 function createApolloClient() {
   return new ApolloClient({
     ssrMode: typeof window === "undefined", // set to true for SSR
     link: new HttpLink({
       uri: "YOUR MAGENTO-ENDPOINTS",
     }),
     cache: new InMemoryCache(),
   });
 }
  • SSR mode true allows to prevent Apollo Client unnecessarily re-fetching of queries, Therefore we set the ssrMode should be true when page is pre-rendered using SSR (Server-Side rendering) but it needs to be false when client is rendered. for achieving this we use typeof the window object to determine uniquely that Apollo client is running on client side or server side.
  • Now we’ve createApolloClient() function that returns the Apollo Client instances for given config. Apollo client will create the new instance for every page. because of that we’ll make a function initializeApollo() which calls the createApolloClient() function to create a new client in case it doesn’t exit , unless we’ll merge the Apollo cache with the initialState (initialState !== null) which is the Apollo cache value that passed in initializeApollo() function.
export function initializeApollo(initialState = null) {
    const _apolloClient = apolloClient ?? createApolloClient();
    /* If your page has Next.js data fetching methods that use Apollo Client, the initial stategets hydrated here*/ 
    if (initialState) {
        // Get existing cache, loaded during client side data fetching
        const existingCache = _apolloClient.extract();
    /* Restore the cache using the data passed from  
getStaticProps/getServerSideProps combined with the existing 
    cached data */
      _apolloClient.cache.restore({ ...existingCache, ...initialState});
    }
    // For SSG and SSR always create a new Apollo Client
    if (typeof window === 'undefined') return _apolloClient;
    // Create the Apollo Client once in the client
    if (!apolloClient) apolloClient = _apolloClient;
    return _apolloClient;
}

We want Apollo client instance to be updated only when cache value is changed
to achieve this , we going to use the useMemo() hook. We make the useApollo() function which return the memoized value of the Apollo client().

Searching for an experienced
Magento 2 Company ?
Read More


export function useApollo(initialState) {
    const store = 
    useMemo(() => initializeApollo(initialState),[initialState]);
    return store;
}

export the client for SSR use.

export const client = initializeApollo();

Step 3: Passing the Apollo Client in Apollo Provider

import { ApolloProvider } from "@apollo/client"
import {useApollo} from "../lib/apollo-client"
export default function App({ Component, pageProps }) {
  const apolloClient = useApollo(pageProps.initialApolloState);
  return (
     <ApolloProvider client={apolloClient}>
       <Component {...pageProps} />
     </ApolloProvider>
  )
}

Now overall we completed the setup of Apollo client and furthermore we going to work on GraphQl Api’s. But Before starting to use GraphQl Api’s need to understand the basics of GraphQl for that you can visit GraphQl Api’s and I also provide the basic guide below.

GraphQl Query and Mutations.
for using GraphQl Api’s we must need to be understand the concept of
mutations and Query.
Query : It’s used for fetching data, just like the GET method in REST API.
Mutation : It’s used for changing the data just like the POST , DELETE , and PUT method in REST API.

// Query example
query Countries {
  country {
    // defining return data
    name 
    code
  }
}
// Mutation example
mutation loginUser($userName: String!, $password: String!) {
  login(username: $userName, password: $password) {
    // defining return data
    id
    email
    firstname
    outlet_id
    lastname
    filename
    user_cart_item_list
  }
}

Now we completed the apollo client and GraphQl basics guide, only thing which left is using implement magento GraphQl Api with our Form.

Implement the magento GraphQl Api’s with NextJS

Mutation for Create Customer Address.
In this mutation you also need to define the schema or you can say type of input values of createCustomerAddress, for that you follow this doc or blog Schema Basic and Types

mutation Create_Customer_Address($input: Create_Customer_Input!) {
  createCustomerAddress(createCustomerAddressData: $input) {
    id
    region {
      region
      region_code
    }
    country_code
    street
    telephone
    postcode
    city
    default_shipping
    default_billing
  }
}
import React, { useState, useEffect } from "react";
import { useForm } from "react-hook-form";
import Create_Customer_Address from "../api/createCustomerAddress.graphql"
const LoginForm = () => {
  const {
    register,
    handleSubmit,
    formState: { errors }, reset
  } = useForm();
  const [formData, setFormData] = useState({});
  const [customerLogin, {data,error,loading] =   useMutation(Create_Customer_Address);
  const formSubmit = (data) => {
    setFormData( {...data} );
    customerLogin(
     variables: {input: formData},)
  };

   useEffect(() => {
       if(data) {
       alert("Customer Address is successfully created")
       reset();
   }
 },[loading])
  return (
    <form onSubmit={handleSubmit(formSubmit)}>
      <div className="form-container">
        <label className="label">Account Information</label>
        <input
          {...register("firstName", { required: true })}
          placeholder="First name"
        />
        {errors.firstName && <p className="error">First Name is required.</p>}
        <input
          {...register("lastName", { required: true, minLength: 2 })}
          placeholder="Last name"
        />
        {errors.lastName && <p className="error">Last Name is required.</p>}
        <input
          {...register("company", { required: true })}
          placeholder="Company"
        />
        <input
          type="email"
          {...register("email", { required: true })}
          placeholder="Email"
        />
        {errors.email && <p className="error">Email address is required.</p>}
        <input
          type="tel"
          {...register("phone", { required: true, valueAsNumber: true })}
          placeholder="Phone Number"
        />
        {errors.phone && <p className="error">Phone Number is required.</p>}
        <label className="label">Address</label>
        <input
          {...register("address", { required: true })}
          placeholder="Street Address"
        />
        {errors.address && <p className="error">Street Address is required.</p>}
        <input {...register("addressL2")} placeholder="Street Address 2" />
        <input {...register("addressL3")} placeholder="Street Address 3" />
        {/* <input type="date"  {...register("date", )} placeholder="date" />  */}
        <input {...register("city", { required: true })} placeholder="City" />
        {errors.city && <p className="error">City name is required.</p>}
        <input
          {...register("zip", { required: true, valueAsNumber: true })}
          placeholder="Zip"
        />
        {errors.zip && <p className="error">Zip Code is required.</p>}
        <input
          type="text"
          {...register("country", { required: true })}
          placeholder="Country"
        />
        {errors.country && <p className="error">Country name is required.</p>}
        <input
          {...register("state", { required: true })}
          placeholder="State/Province"
        />
        {errors.country && <p className="error">State/Province is required.</p>}
      </div>
      <div className="formData">
        <input className="btn" type="submit" value="Save" />
        <div className="formValues">
          <p className="values">{formData.firstName}</p>
          <p className="values">{formData.lastName}</p>
          <p className="values">{formData.company}</p>
          <p className="values">{formData.email}</p>
          <p className="values">{formData.phone}</p>
          <p className="values">
            {formData.address} {formData.addressL2} {formData.addressL3}    {" "}
          </p>
          <p className="values">{formData.city}</p>
          <p className="values">{formData.zip}</p>
          <p className="values">{formData.country}</p>
          <p className="values">{formData.state}</p>
        </div>
      </div>
    </form>
  );
};
export default LoginForm;

Here we make the mutation of Create_Customer_Address in which we send the data of user and after mutation get successfully called we called the alert() and reset the field method to indicate that user data is successfully added.
Query for get Customer Details.
In this Query we get the detail of our customer. and we going to use useQuery() hook for execute our query.

query Get_Customer_Details{
  customer {
    firstname
    middlename
    lastname
    suffix
    prefix
    gender
    date_of_birth
    taxvat
    created_at
    default_shipping
    default_billing
    email
    is_subscribed
    addresses {
      firstname
      lastname
      street
      city
      region {
        region_code
        region
      }
      postcode
      vat_id
      country_code
      telephone
      company
    }
  }
}
import React from 'react'
import { useQuery } from '@apollo/client'
import Get_Customer_Details from "../api/query/getCustomerDetail.graphql";
const CustomerDetails = () => {
    const {data, loading, error} = useQuery(Get_Customer_Details)
  return (
     <React.Fragment>
    {loading ? (<h1>Loading</h1>) : (
      <h1>{`${data.customer.firstname} ${data.customer.lastname}`}</h1>
    )}
    </React.Fragment>
  )
}
export default CustomerDetails;

so this is how you Implement Magento GraphQl Api’s with NextJS,
Stay tuned for more updates.

Happy Coding !!

Source: webkul.com