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
mapfunction, 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/studiodirectory from the exercises and studio repo.Explore the codebase.
Look at the
Appfunction.You can see the list of components.
9 10 11 12 13 14 15 16 17 18 19 20export default function App() { return ( <> <RecipeImage /> <RecipeName /> <RateARecipe rating={5} /> <Button saveButton={true} /> <AuthorInfo /> <IngredientList /> </> ); }Notice that both
RateARecipeandButtonhave variables.RateARecipetakes a number andButtontakes 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
componentsfolder:- Open the
recipe.jsonfile 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.jsxfile inside thecomponentsfolder. You will see an array of star emojis. These will be our rating system for the Pin.Inside
RateARecipecreate a new function, that will also take props.Let’s name it
GiveRating. This function will return the number of stars passed toRateARecipe.GiveRatingwill use the number passed toRateARecipeto index through thestarsarray. 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 6function GiveRating() { return <h3>{stars[props.rating - 1]}</h3>; }
GiveRatingis nested insideRateARecipeand 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 renderGiveRatingelse rendernull.Test this in the
Appfunction 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.
SaveButtonandClickedButtonrender the buttons in the browser. Both of these components contain an alert to verify we can click each button.- The
Buttoncomponent will render either button based on a conditional. We will be using a boolean in theAppfunction 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
SaveButtonfile 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
buttonclass contains anidfor 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
clickedButtonas 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.
Buttonfunction should take an argument, such asprops.Create a variable that defines the
props. Name the variablesaveButton.5const saveButton = props.saveButton;Create a conditional that does the following:
- If the
saveButtonvariable istrue, thenSaveButtonwill render - else
ClickedButtonwill appear.
- If the
In the
Appfunction, theButtoncomponent hassaveButtonequal totrue.Test the conditional by changing
saveButtonin theAppfunction 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
RecipeNamecomponent. - Render the recipe’s name as an
<h1>level header. returntherecipeNamevariable.
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
classNameequal torecipeImage.
- Use the
- Return
recipeImageinside 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.
IngredientsListwill 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
mapfunction will iterate through the ingredients usingidas 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 thekeyequal 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
authorImageas 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 24return ( <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.