Querying Data with ApolloGraphQL
Tags: react, graphql, apollo, nextjs
Published: 2021-05-12 03:03:13

After completing the coursework at Flatiron, I felt accomplished but eager to keep learning the wide world of software development and the myriad of coding languages. Knowing my indecisive habit, I luckily had purchased a premium course tutorial called Advanced React that I was excited to start. While I was familiar with React and Redux, this training offered an introduction to other coding platforms including Next.js and ApolloGraphQL. 

One of the biggest differences I noticed was the process of fetching data to be displayed on the frontend. In React, once the page is mounted onto the UI, an initial fetch function is initiated in an action directory. That action must be executed to retrieve the data from the API that is then converted into JSON format and then dispatched to a reducer. The reducer would be responsible for initializing and updating state with the data or payload.

```
export function fetchProducts() {
    return (dispatch) => {
        dispatch({type: 'LOADING_PRODUCTS'})
        fetch('http://localhost:3000/api/v1/products').then(resp => resp.json())
        .then(users => dispatch({
            type: 'FETCH_PRODUCTS',
            payload: products
        }))
    }
}
```
```
export default function usersReducer(state = {users: [], loading: false}, action) {
    switch(action.type) {
        
        case 'LOADING_USERS':
            return {
                users: [...state.users],
                loading: true
            }
        case 'FETCH_USERS':
            return {users: action.payload.data,
                loading: false
            }
    }
}
   
```
With ApolloGraphQL, a query is made directly in the component designated to display the data. First, a constant variable is created that defines the query request from the database, including associated relationships, such as a table of products and a table of product images. This is wrapped in a GraphQL tag called gql, as opposed to writing out JSON 

```
import { useQuery } from "@apollo/client"
import gql from "graphql-tag"
import Product from "./Product";

export const ALL_PRODUCTS_QUERY = gql`
    query ALL_PRODUCTS_QUERY() {
        allProducts() {
            id
            name
            price
            description
            photo {
                id
                image {
                    publicUrlTransformed
                }
            }
        }
    }
`;
```

Next, within the component, the data is saved to a variable using the useQuery hook provided by Apollo. This will return an object that includes the data as well the loading state and any errors. The data can then be mapped over to render the details. 

```
export default function Products() {
    const {data, error, loading} = useQuery(ALL_PRODUCTS_QUERY)
    if (loading) return <p>Loading...</p>;
    if (error) return <p>Error: {error.message}</p>;
    return (
        <div>
             {data.allProducts.map(product => (
                 <Product key={product.id} product={product} />
             ))}
        </div>
    )
}
```

In order to fetch and render from the API, a new instance of `ApolloClient` must be performed to connect the UI with the desired database. Included in its parameters are the `uri` of the database and an instance of `InMemoryCache` to store the data. 

What I find most helpful is the database's url is only provided in one document while different actions can be defined and initiated within the components. The products component will make a query for all products, the create product component will create a new instance of a product, without having to define the API url each time. This seems more concise when compared to the numerous action files made to handle CRUD actions in Redux.