
This is my first technical document on React! I started building on Next.js before my bootcamp taught React Lectures 2 and React Lecture 3. React is not a requirement for our project and yet I decided to build my entire front-end with React utilizing Next.js. I’ve only been coding towards a career for 5 months, so bare with my communicability and feel free to offer love and support in the comments!

To get a Favorite Button Functional Component to render using React (Next.js), you likely will run into a lot of hook errors. The main one that caused me problems is:
Unhandled Runtime Error Error: Rendered more hooks than during the previous render.
– Error Message
When you have hooks in the same component, they expect the same amount of hooks to render each time a render is called! That doesn’t really work well with favorite buttons. Especially if your favorite button has 3 hooks: the first renders once (to find and set the user
), the second renders based on the response of the first one (to find favBool
if the recipe is currently a favorite or not), and the last one renders every onClick
(every time a user favorites and unfavorites)!
A work around is to identify all your hooks and find a way to split them into their own functional components. What if the hooks are all a part of the same component? That was exactly my frustration. ONE ity-bity 20x20px favorite button needs THREE hooks!
That’s where coding creativity lies until google searches and React documentation readily offers you a clearer solution. The favorite button code can be split into three functional components so essentially the component calls a component that calls a component!
Here is all my raw code on a github Gist that I’m having technical issues embedding on WordPress. Feel free to copy and paste into a code editor for better readability. Below I outline how my code works.
PART 1: My Imports
- Next.js graciously holds all your CSS in a style folder, I used styles for my
.favorite-button
and.text_small
which rendered if the User wasn’t logged in. React, {useState, useEffect }
are all being used.useState
remembers the user logged in, whether or not the recipe is favorited, and toggling the recipe (I learned toggling from Codecademy’s state hook lesson!).useEffect
checkslocalStorage
if the user is logged inuseSWR
is the Next.js solution to dynamic routing- Font Awesome Icons were suggested to me by my mentor! I ended up downloading their entire free library to use on my project. My project is now icon heavy because I am just amazed how easy it was to implement!
/components/favoritebutton.js
"use strict";
import styles from '../styles/Home.module.css';
import React, { useState, useEffect } from 'react';
import useSWR from 'swr'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faHeart, faHeartBroken } from '@fortawesome/free-solid-svg-icons'
Part II: Check if a User is logged in

- Debug with
console.log
often includedprops
I passed from my parent component passed correctly. I passed the parameterrecipeId
. - I set the
user
tonull
usinguseState
. - With
useEffect
, I retrieved user fromlocalStorage
that was set when theuser
logged in - Debug with
console.log
often including to see if the user is correctly stored. - If the
user
did not exist in local storage, the button is not rendered. Instead,return
a link to log-in. (Thespan
is there only because I’m highlighting my text overlayed on a background image of the recipe) return
another component with the next hook that finds the initial state of the user favorite! Pass it theuserId
andrecipeId
. Don’t be silly by passing allprops
! Also, removeprops
from the variable name so you don’t need to call the variable usingprops.props.props.....recipeId
.>.<
/components/favoritebutton.js
function FavoriteButton(props) {
console.log(props)
const [user, setUser] = useState(null);
useEffect(() => {
const loggedInUser = localStorage.getItem('user');
if (loggedInUser) {
setUser(JSON.parse(loggedInUser));
}
}, []);
console.log("This is the user saved in local storage:", user)
// IF USER IS NOT IN LOCAL STORAGE, ASKED TO LOG IN INSTEAD
if (user === null) {
return (
<p className={styles['text_small']}><span>
<a href="/login">Log in to favorite this recipe!</a>
</span></p>);
}
return <FindInitialState userId={user.user_id} recipeId={props.recipeId}/>
}
Part III: Render a favorite button if a User is logged in
- Pass in the
props
from the previous component - Declare a
favBool
that will eventually have a value of true or false fetch
whether a user/recipe relationship exists- Debug with
console.log
often - Have the component show the user a preloader as the button is rendering
- Since you used a hook (
useSWR
) to retrieve the data, do not use another hook in this component return
another component with the next hook that adds and deletes from your database using a Toggle. Pass infavBool
,userId
, andrecipeId
(or whatever variables are needed for your toggle to work)!
/components/favoritebutton.js
function FindInitialState(props) {
let favBool;
const fetcher = url => fetch(url).then(r => r.json())
const { data, error } = useSWR(`/api/users/${props.userId}/recipes/${props.recipeId}`, fetcher)
console.log("This user has this recipe favorited?", data)
if (error) return <div>failed to load</div>
if (data === undefined) return <div>loading...</div>
favBool = data;
return <SetStateAndToggle favBool={favBool} userId={props.userId} recipeId={props.recipeId}/>
}
Part IV: set
Favorite and toggleFavorite
modifying the GUI and your back-end!

I removed my comments in my code since this component is dense and the explanation is here:
- Define the font awesome icons as variables (
currentlyAFavorite
ornotCurrentlyAFavorite
) - Set user’s favorite to the
favBool
found with the hook of the last component - Declare a
toggleFavorite
variable that takes inrecipeId
- If
favorite
is currently true, clicking will unfavorite andfetch
a post request that removes the recipe to the User/Recipe datatable on the back-end - Debug using
console.log
often! - If the
favorite
is false to start, clicking will favorite andfetch
a post request that adds the recipe that will add the recipe to the User/Recipe datatable on the backend - For the
toggleFavorite
function,return !favorite
will toggle the button to the opposite boolean return
the favorite button that uses your CSS styling,onClick
handlestoggleFavorite
which will using the ternary offavorite === true
- Finally,
export {FavoriteButton}
component from Part II (which hasFindInitialState
component andSetStateAndToggle
component nested into it) so you can render your button whatever parent component (e.g.DetailedRecipeComponent
) not on this documentation.
/components/favoritebutton.js
function SetStateAndToggle(props) {
const currentlyAFavorite = <FontAwesomeIcon icon={faHeart} />
const notCurrentlyAFavorite = <FontAwesomeIcon icon={faHeartBroken}/>
const [favorite, setFavorite] = useState(props.favBool);
const toggleFavorite = (recipeId) => {
setFavorite((favorite) => {
if (favorite == true) {
console.log("I clicked unfavorite")
console.log(props)
fetch(`/api/users/${props.userId}/recipes/${recipeId}/remove`, { method: 'POST' })
.then(console.log("This was a favorited recipe, but now it isnt!"));
}
if (favorite == false) {
console.log("I clicked favorite")
fetch(`/api/users/${props.userId}/recipes/${recipeId}/add`, { method: 'POST' })
.then(console.log("This was not a favorited recipe. Now it is!"));
}
return !favorite;
});
}
return (
<button
className={styles['favorite-button']}
onClick={() => toggleFavorite(props.recipeId)}
key={props.recipeId}>
{ favorite === true ? currentlyAFavorite : notCurrentlyAFavorite}
</button>
);
}
export {FavoriteButton};

I hope this was helpful and informative. Feel free to show me love below. This was today’s breakthrough learning moment as I’m 5 months into coding toward a career and Week 3 of building my first app, let alone with React! I wonder where all my learning will take me next.