indiejesus2
Posted on May 12, 2021
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.
Posted on May 12, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.