In this lesson, you'll learn how JSX and React components can work together, and you'll become more comfortable with both concepts while learning some new tricks.
Let's consider this block of HTML code:
<blockquote>
<p>
It always seems impossible until it's done.
</p>
<cite>
<a target="_blank" href="https://en.wikipedia.org/wiki/Nelson_Mandela">
Nelson Mandela
</a>
</cite>
</blockquote>
Now, how can we make a React component that returns this HTML structure?
You can check out the QuoteMaker.js
file to see one way of achieving it.
One important thing to notice in QuoteMaker
is the use of parentheses ()
in the return statement on lines 4 and 16. Up until now, your function components' return statements might have looked like this, without any parentheses:
return <h1>Hello world</h1>;
However, when you have a multi-line JSX expression, it should always be wrapped in parentheses! That's why the return statement in QuoteMaker
has parentheses around it.
In MyQuote.js
, write a React component that returns a quote that inspires you.
Use QuoteMaker.js as a guide! Remember to import React at the top of the file, and remember to export your component at the bottom of the file.
You have probably noticed by now, that in JSX, just like in HTML, you can nest JSX elements inside other JSX elements, forming a hierarchical structure.
Here's an example of a JSX <h1>
element nested inside a JSX <a>
element:
<a href="https://www.example.com"><h1>Click me!</h1></a>
To improve readability, you can use HTML-style line breaks and indentation:
<a href="https://www.example.com">
<h1>
Click me!
</h1>
</a>
When a JSX expression spans multiple lines, it's important to wrap the multi-line JSX expression in parentheses:
(
<a href="https://www.example.com">
<h1>
Click me!
</h1>
</a>
)
Nested JSX expressions can be assigned to variables, passed as function arguments, or used in any other way that non-nested JSX expressions can. Here's an example of a nested JSX expression saved as a variable:
const theExample = (
<a href="https://www.example.com">
<h1>
Click me!
</h1>
</a>
);
By leveraging nested JSX, you can create complex and structured JSX components to build dynamic and interactive user interfaces in React.
Follow the instructions in div.js.
There is an important rule in JSX that we haven't mentioned yet: a JSX expression must have exactly one outermost element.
Let's illustrate this rule with an example:
// Which example is valid jsx?
const paragraphs = (
<div id="i-am-the-outermost-element">
<p>I am a paragraph.</p>
<p>I, too, am a paragraph.</p>
</div>
);
const paragraphs = (
<p>I am a paragraph.</p>
<p>I, too, am a paragraph.</p>
);
In the first example, the JSX expression has a single outermost element, which is the <div>
element. Inside the <div>
, we have two <p>
elements.
However, the second example violates the rule. It tries to have two outer elements, two <p>
elements without being wrapped in another element. This is not allowed in JSX.
If you encounter a situation where your JSX expression has multiple outer elements, the solution is straightforward: wrap the entire JSX expression in a <div>
element (or any other suitable wrapper element).
By ensuring that your JSX expression has a single outermost element, you can avoid errors and ensure that your JSX code is valid and well-structured.
Follow the instructions in blog.js
Variable attributes in react, are like containers inside a component that can hold different types of information. Imagine a box with different labels on it, where you can store and retrieve things.
In React, these attributes allow you to store and manage data within a component. For example, you can have a variable inside a component to hold a number, a piece of text, or even a list of items.
Attributes can also control how a component looks and behaves. You can have an attribute that determines the color of a button or the size of a text box.
Another important use of attributes is passing data between components. You can pass information from a parent component to a child component using attributes called "props." This allows you to customize and configure the child component based on the values provided by the parent.
Think of component variable attributes as the knobs and switches that let you control the behavior, appearance, and functionality of your React components. They are like little containers that hold important information and allow components to interact with each other in a flexible way.
Take a look at this JavaScript object named redPanda:
const redPanda = {
src: 'https://upload.wikimedia.org/wikipedia/commons/b/b2/Endangered_Red_Panda.jpg',
alt: 'Red Panda',
width: '200px'
};
How could you render a React component with an image of redPanda
and its properties?
Select RedPanda.js
to see one way to do this.
Go to MyQuote.js
, and follow the instructions given under Part 2 .
A function component is required to have a return statement, but it can also contain other things, like simple calculations that need to be performed before returning the JSX element.
Here's an example of performing calculations inside a function component:
function RandomNumber() {
// First, some logic that needs to happen before returning
const n = Math.floor(Math.random() * 10 + 1);
// Next, a return statement that uses the calculated logic
return <h1>{n}</h1>;
}
Be careful to avoid a common mistake like this:
function RandomNumber() {
return (
const n = Math.floor(Math.random() * 10 + 1);
<h1>{n}</h1>
)
}
What is wrong with the code above?
In the above example, the line with the const n
declaration is incorrect because it should come before the return
statement. Placing it inside the return block will cause a syntax error.
We can try it together in the Friend.js file.
import React from 'react';
const friends = [
{
title: "Yummmmmmm",
src: "https://content.codecademy.com/courses/React/react_photo-monkeyweirdo.jpg"
},
{
title: "Hey Guys! Wait Up!",
src: "https://content.codecademy.com/courses/React/react_photo-earnestfrog.jpg"
},
{
title: "Yikes",
src: "https://content.codecademy.com/courses/React/react_photo-alpaca.jpg"
}
];
function RandomFriend() {
// Generate a random index to select a friend
const randomIndex = Math.floor(Math.random() * friends.length);
// Get the randomly selected friend
const randomFriend = friends[randomIndex];
// Render the JSX
return (
<div>
<h1>{randomFriend.title}</h1>
<img src={randomFriend.src} alt={randomFriend.title} />
</div>
);
}
export default RandomFriend;
In this example:
- We import React to use JSX syntax and define the
friends
array containing objects withtitle
andsrc
properties representing friends and their corresponding image URLs. - We create a functional component called
RandomFriend
. - Inside the
RandomFriend
component, we generate a random index usingMath.random()
andMath.floor()
functions. This index will be used to select a random friend from thefriends
array. - We retrieve the randomly selected friend from the
friends
array using the random index. - We render JSX within the return statement, displaying the title of the random friend as a heading (
<h1>
) and the corresponding image using thesrc
andalt
attributes. - Finally, we export the
RandomFriend
component as the default export, allowing it to be imported and used in other files.
When you use the RandomFriend
component in your application, it will render a random friend each time it is rendered or re-rendered.
Refactor the code in MyQuote.js
to have similar functionality as the Friend.js
component. Create an array called quotes
with objects containing title
and src
properties. Inside the MyQuote
functional component, generate a random index using Math.random()
and Math.floor()
, and retrieve a random quote from the quotes
array. Render a heading element displaying the quote's title
property and an image element using the src
property. Save the changes, import MyQuote
in App.js
, and render the MyQuote
component. When running the React development server, MyQuote
will randomly render a quote from the array each time it is rendered or re-rendered.
To use a conditional statement inside a function component, you can follow this approach:
It's important to note that the if
statement is located inside the function component, but before the return
statement.
This is how it might look:
function TodaysPlan() {
const weather = 'sunny';
if (weather === 'sunny') {
return <p>Today's plan: Go to the beach!</p>;
} else {
return <p>Today's plan: Stay at home and code.</p>;
}
}
In the above example, we have a variable weather
with the value 'sunny'
. The conditional statement checks if the weather is sunny, and if it is, it returns the JSX element <p>Today's plan: Go to the beach!</p>
. Otherwise, if the weather is not sunny, it returns the JSX element <p>Today's plan: Stay at home and code.</p>
.
Remember to place the conditional statement before the return
statement within the function component.
Refactor the Quote.js
component to include a condition in the rendering logic. Choose a condition based on your desired requirement, such as displaying an additional element only if a certain prop value is true. Inside the component's JSX structure, add an if
statement or a conditional (ternary) operator to check the condition. Provide the JSX content to render when the condition is met, and optionally, an alternative content if the condition is not met. Save the changes, run the development server, and observe how the component's rendering adapts based on the condition you added. This task allows you to practice incorporating conditional rendering into your React components.
In React, JSX allows us to write HTML-like code within our JavaScript components. When combined with the .map()
method, we can easily generate dynamic elements based on the contents of an array.
JSX is a syntax extension that bridges the gap between the visual representation of our UI and the underlying logic. It enables us to express our UI components in a familiar HTML-like format, making it more intuitive and readable.
The .map() method, on the other hand, is a powerful JavaScript function that iterates over each item in an array. It allows us to apply a transformation to each item and generate a new array of React elements. This means we can dynamically create UI components based on the data we have.
To ensure optimal performance, it's important to assign a unique "key" prop to each rendered element. The key serves as a special identifier that helps React efficiently update and manage the elements. It's like giving each element a distinct label, allowing React to keep track of them more effectively.
Let's consider the following example:
import React from 'react';
const MyComponent = () => {
const data = ['Apple', 'Banana', 'Orange'];
return (
<ul>
{data.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
};
export default MyComponent;
In this example, we have an array of fruits stored in the data
variable. By using .map()
, we iterate over each fruit, dynamically creating <li>
elements with the fruit name as their content. The key={index}
assigns the index of each item in the array as its unique key.
Back in MyQuote.js
, change the logic of your JSX to render all the quotes stored in your quotes
array.
You can include event handlers in your function components to run specific code in response to interactions with the user interface, such as clicking.
Let's take a look at an example:
function MyComponent() {
function handleHover() {
alert('Stop it. Stop hovering.');
}
return <div onHover={handleHover}></div>;
}
In the above example, we have an event handler called handleHover()
. It is defined inside the function component and, by convention, starts with the word "handle" followed by the type of event it is handling.
The logic for what should happen when the <div>
is hovered over is contained within the handleHover()
function. The function is then passed as a prop to the <div>
element using the onHover
attribute.
Event handler functions are defined within the function component and are usually triggered by specific events.
One thing to watch out for is that when passing the event handler function, such as handleHover
, as a prop, we don't include parentheses after the function name. For example:
return <div onHover={handleHover}></div>;
This is because passing it as handleHover
indicates that it should be called only when the event occurs. If we were to pass it as handleHover()
, it would immediately trigger the function instead of waiting for the event, so be cautious!
Instructions:
- Open the
MyQuote.js
file in your code editor. - Locate the JSX structure inside the
return
statement. - Add a button element (
<button>
) at the desired location within the JSX structure. This button will refresh the page to to render a random quote. - Assign an
onClick
event handler to the button element, using the provided code snippet:onClick={handleRefresh}
. - Define the
handleRefresh
function within theMyQuote
component. This function will be responsible for refreshing the page and triggering a new render with a new random quote from thequotes
array. - Use your favorite search engine to figure out how to refresh your page with react.
- Inside the
MyQuote
component, use the provided code snippet to generate a random index and store it in a variable:const randomIndex = Math.floor(Math.random() * quotes.length);
. - Retrieve the randomly selected quote from the
quotes
array using the random index:const randomQuote = quotes[randomIndex];
. - Modify the JSX structure inside the
return
statement to display the selected quote by replacing the existing quote content withrandomQuote.title
andrandomQuote.src
in the appropriate places. - Save the changes to
MyQuote.js
. - Test the functionality by clicking the "Random Quote" button. You should see a random quote being displayed each time the button is clicked.
Expected Result:
After completing the steps, you should have a working "Random Quote" button in the MyQuote
component. Clicking the button will select a random quote from the quotes
array and display it on the page. Each click should result in a different quote being shown.
Remember to consult the React documentation or other learning resources for guidance and assistance while completing this task. Happy coding!