Studio
In this studio, you will make a second Pinterest-inspired application. This studio will add conditional rendering and the map
function to the project.
The app you complete in this studio will have the following functionality:
- A star rating component that can be updated to display 0 - 5 stars.
- The ability to mimic the Save vs Saved button on a Pinterest pin using conditional rendering.
- Displaying specific recipe information using the
map
function, if necessary, and a JSON file. - CSS styling has been created for this project. The instructions will let you know what and how to style elements.
Getting Started
Check out the application in the
part2/studio
directory from the exercises and studio repo.Explore the codebase.
Look at the
App
function.You can see the list of components.
9 10 11 12 13 14 15 16 17 18 19 20
export default function App() { return ( <> <RecipeImage /> <RecipeName /> <RateARecipe rating={5} /> <Button saveButton={true} /> <AuthorInfo /> <IngredientList /> </> ); }
Notice that both
RateARecipe
andButton
have variables.RateARecipe
takes a number andButton
takes a boolean.
We will be providing the code (hard coding) for this app to render conditionally. Keep that in mind as you work on this studio. Test things by changing these variables here.
In the
components
folder:- Open the
recipe.json
file and populate the values with data from a recipe you find online. This can be the same recipe you used in Part 1 or a new recipe. - Save the file.
- Open the
Part 1: RateARecipe
Desired Output: The RateARecipe
function should return 0-5 stars. The number of stars rendered will be determined by passing the function an argument.
Open the
RateARecipe.jsx
file inside thecomponents
folder. You will see an array of star emojis. These will be our rating system for the Pin.Inside
RateARecipe
create a new function, that will also take props.Let’s name it
GiveRating
. This function will return the number of stars passed toRateARecipe
.GiveRating
will use the number passed toRateARecipe
to index through thestars
array. You will need to apply some math to make the array output match the number of stars rendered.Return the rating at least an
<h3>
level header.4 5 6
function GiveRating() { return <h3>{stars[props.rating - 1]}</h3>; }
GiveRating
is nested insideRateARecipe
and is returning the number of stars. Next, let’s add a conditional to make sure a user only provides a number between 1-5.Create a ternary that checks the value of
props
. If the number is between 1 and 5, then renderGiveRating
else rendernull
.Test this in the
App
function by updating the value ofrating
.
Part 2: Buttons
Let’s explore the buttons! A Pinterest pin has a red button with the word “Save” printed on it. When a user clicks that button, it switches to black with the word “Saved”.
There are 3 components for the buttons.
SaveButton
andClickedButton
render the buttons in the browser. Both of these components contain an alert to verify we can click each button.- The
Button
component will render either button based on a conditional. We will be using a boolean in theApp
function to serve as our “click”
SaveButton
Desired Output: A Red button with rounded corners which reads “Save” in white letters. If you hover over it, the red changes to a darker red. When you click the button, a pop appears that reads “You are saving this pin!”.
This button has already been created. You can use its code to help you create ClickedButton
component.
- Open the
SaveButton
file and explore the code. An alert has been added to demonstrate that you clicked the button. - When you click the Save button on a Pinterest pin, it will share a notification that you Saved the pin to a board.
- The
button
class contains anid
for the CSS needed to make the button red. The CSS has already been created in thestyling.css
. The styling also changes when you hover over the button. It’s unique to this button.
If you want to check how SaveButton
works, you can nest it inside the App
function. You can try this with any of the components you are creating.
Be sure to remove it once you have a working Button
component.
ClickedButton
Desired Output: A black button with rounded corners. The word has changed to “Saved”. When you click on this button a message about removing the pin appears.
- Move into
ClickedButton.jsx
. It should function like the Save button, but it should display “Saved” instead of “Save”, and be black instead of red. - For the styling, you can apply
clickedButton
as theid
. This is found in the CSS styling which will need to be imported. - It should also have an alert that lets a user know that when you click it the pin is removed from the board.
Button
Desired Output: Returns either SaveButton
or ClickedButton
based on the boolean value.
This function will hold the logic that will determine which button will appear in the browser.
You will need to create a conditional that will render SaveButton
or ClickedButton
.
Button
function should take an argument, such asprops
.Create a variable that defines the
props
. Name the variablesaveButton
.5
const saveButton = props.saveButton;
Create a conditional that does the following:
- If the
saveButton
variable istrue
, thenSaveButton
will render - else
ClickedButton
will appear.
- If the
In the
App
function, theButton
component hassaveButton
equal totrue
.Test the conditional by changing
saveButton
in theApp
function tofalse
.
Part 3: Add the Recipe Data
The remaining components will be using the recipe.json
file. You will need to import this file into each component. We can also use the map
function to find the desired keys if it makes sense to you.
Recipe Name
Desired Output: This function needs to return the recipe name as an <h1>
level header.
- Open the
RecipeName
component. - Render the recipe’s name as an
<h1>
level header. return
therecipeName
variable.
Image
Desired Output: Returns the image of the recipe from the JSON.
- Import the recipe JSON file.
- Find the
recipeImage
.- Use the
<img>
tag. You can pass the recipe name to the alt text value. - Styling has been created for the image. If you would like to apply it set the
className
equal torecipeImage
.
- Use the
- Return
recipeImage
inside its own<div>
.
Ingredient Lists
Desired Output: Create an unordered list of ingredients.
This component will map over a list of ingredients. The ingredients are contained within an array inside our JSON object. We will create a map
function to iterate through the array of ingredients.
- Import the recipe.
IngredientsList
will return a single<div>
that holds an<h3>Ingredients</h3>
header.- Create a list object by placing our map inside curly braces. In the other components, we used a variable to hold our map output. In this component, we will return the list as we render it.
- The
map
function will iterate through the ingredients usingid
as a key.
Author Info
Desired Output: A single component that returns the author’s name, image, and URL. There is CSS for the image that you can set if you desire.
Import the recipe and styling.
Let’s start by creating a variable that will return the author’s name. Create a
<div>
that returns the value of theauthor
. You can set thekey
equal to thename
.Create a second variable that will use the map function to return the author’s image.
- Set the alt text equal to the author’s name.
- Apply the
authorImage
as theclassName
.
Finally, create the final variable that will host the URL. Return the link using the
<a>
tag. The URL can be the context between the opening and closing tags.Return all variables in a final
<div>
.18 19 20 21 22 23 24
return ( <div> {recipeAuthorImage} {recipeAuthor} {recipeWebsite} </div> );
Wrapping Up
Congrats! You’ve finished the studio! Make sure that you stage
, commit
, and push
your work up to GitHub.