Most modern websites are driven by two things: data and user demands. This shouldn't come as a surprise, as the ability to personalize user data is the cornerstone of real-world web development today. And as user demands evolve, applications need to be more performant.
This application was created by taking starter code with a fully functioning Google Books API search engine built with a RESTful API, and refactoring it to be a GraphQL API built with Apollo Server. The final app was built using the MERN stack with a React front end, MongoDB database, and Node.js/Apollo server and GraphQL API.
To refactor the code, the following was performed:
-
Set up an Apollo Server to use GraphQL queries and mutations to fetch and modify data, replacing the existing RESTful API.
-
Modify the existing authentication middleware so that it works in the context of a GraphQL API.
-
Create an Apollo Provider so that requests can communicate with an Apollo Server.
AS AN avid reader
I WANT to search for new books to read
SO THAT I can keep a list of books to purchase
GIVEN a book search engine
WHEN I load the search engine
THEN I am presented with a menu with the options Search for Books and Login/Signup and an input field to search for books and a submit button
WHEN I click on the Search for Books menu option
THEN I am presented with an input field to search for books and a submit button
WHEN I am not logged in and enter a search term in the input field and click the submit button
THEN I am presented with several search results, each featuring a book’s title, author, description, image, and a link to that book on the Google Books site
WHEN I click on the Login/Signup menu option
THEN a modal appears on the screen with a toggle between the option to log in or sign up
WHEN the toggle is set to Signup
THEN I am presented with three inputs for a username, an email address, and a password, and a signup button
WHEN the toggle is set to Login
THEN I am presented with two inputs for an email address and a password and login button
WHEN I enter a valid email address and create a password and click on the signup button
THEN my user account is created and I am logged in to the site
WHEN I enter my account’s email address and password and click on the login button
THEN I the modal closes and I am logged in to the site
WHEN I am logged in to the site
THEN the menu options change to Search for Books, an option to see my saved books, and Logout
WHEN I am logged in and enter a search term in the input field and click the submit button
THEN I am presented with several search results, each featuring a book’s title, author, description, image, and a link to that book on the Google Books site and a button to save a book to my account
WHEN I click on the Save button on a book
THEN that book’s information is saved to my account
WHEN I click on the option to see my saved books
THEN I am presented with all of the books I have saved to my account, each featuring the book’s title, author, description, image, and a link to that book on the Google Books site and a button to remove a book from my account
WHEN I click on the Remove button on a book
THEN that book is deleted from my saved books list
WHEN I click on the Logout button
THEN I am logged out of the site and presented with a menu with the options Search for Books and Login/Signup and an input field to search for books and a submit button
The web application's appearance and functionality:
As you can see in the following animation, a user can type a search term (in this case, "star wars") in a search box and the results appear:
The user can save books by clicking "Save This Book!" under each search result, as shown in the following animation:
A user can view their saved books on a separate page, as shown in the following animation:
In order for this application to use a GraphQL API,I needed to refactor the API to use GraphQL on the back end and add some functionality to the front end. The following sections contain details about the files I modified on the back end and the front end.
I completed the following tasks in each of these back-end files:
-
auth.js
: Update the auth middleware function to work with the GraphQL API. -
server.js
: Implement the Apollo Server and apply it to the Express server as middleware.Important: Apollo Server recently migrated to Apollo Server 3. This major-version release impacts how Apollo Server interacts in an Express environment. To implement Apollo Server 2 as demonstrated in the activities, you MUST use the following script
npm install [email protected]
to install Apollo Server 2. Alternately, to migrate to the latest version of Apollo Server, please refer to the Apollo Server Docs on Migrating to Apollo Server 3 and Apollo Server Docs on Implementing Apollo Server Express with v3. Note that if you are using Apollo Server 3 you are required useawait server.start()
before callingserver.applyMiddleware
. -
Schemas
directory:-
index.js
: Export your typeDefs and resolvers. -
resolvers.js
: Define the query and mutation functionality to work with the Mongoose models.Hint: Use the functionality in the
user-controller.js
as a guide. -
typeDefs.js
: Define the necessaryQuery
andMutation
types:-
Query
type:me
: Which returns aUser
type.
-
Mutation
type:-
login
: Accepts an email and password as parameters; returns anAuth
type. -
addUser
: Accepts a username, email, and password as parameters; returns anAuth
type. -
saveBook
: Accepts a book author's array, description, title, bookId, image, and link as parameters; returns aUser
type. (Look into creating what's known as aninput
type to handle all of these parameters!) -
removeBook
: Accepts a book'sbookId
as a parameter; returns aUser
type.
-
-
User
type:-
_id
-
username
-
email
-
bookCount
-
savedBooks
(This will be an array of theBook
type.)
-
-
Book
type:-
bookId
(Not the_id
, but the book'sid
value returned from Google's Book API.) -
authors
(An array of strings, as there may be more than one author.) -
description
-
title
-
image
-
link
-
-
Auth
type:-
token
-
user
(References theUser
type.)
-
-
-
I created the following front-end files:
-
queries.js
: This will hold the queryGET_ME
, which will execute theme
query set up using Apollo Server. -
mutations.js
:-
LOGIN_USER
will execute theloginUser
mutation set up using Apollo Server. -
ADD_USER
will execute theaddUser
mutation. -
SAVE_BOOK
will execute thesaveBook
mutation. -
REMOVE_BOOK
will execute theremoveBook
mutation.
-
Additionally, I completed the following tasks in each of these front-end files:
-
App.js
: Create an Apollo Provider to make every request work with the Apollo Server. -
SearchBooks.js
:-
Use the Apollo
useMutation()
Hook to execute theSAVE_BOOK
mutation in thehandleSaveBook()
function instead of thesaveBook()
function imported from theAPI
file. -
Make sure you keep the logic for saving the book's ID to state in the
try...catch
block!
-
-
SavedBooks.js
:-
Remove the
useEffect()
Hook that sets the state forUserData
. -
Instead, use the
useQuery()
Hook to execute theGET_ME
query on load and save it to a variable nameduserData
. -
Use the
useMutation()
Hook to execute theREMOVE_BOOK
mutation in thehandleDeleteBook()
function instead of thedeleteBook()
function that's imported fromAPI
file. (Make sure you keep theremoveBookId()
function in place!)
-
-
SignupForm.js
: Replace theaddUser()
functionality imported from theAPI
file with theADD_USER
mutation functionality. -
LoginForm.js
: Replace theloginUser()
functionality imported from theAPI
file with theLOGIN_USER
mutation functionality.
© 2021 Trilogy Education Services, LLC, a 2U, Inc. brand. Confidential and Proprietary. All Rights Reserved.