Assume we have a JavaScript program that is trying to render a React.js component called Header like so:
<Header memberType='admin' />
Complete the code for the Header component so that it can render the nested AdminAccess component successfully.
import React from 'react';
import AdminAccess from './AdminAccess';
import NavBar from './NavBar';
export class Header extends React.Component {
render() {
if (this.props.memberType === 'admin') {
return <AdminAccess />;
} else {
return <NavBar />
}
}
}
━━━━━━━━━★
The following React.js program uses a component named Menu to render menu items to an application.
Complete the component by filling in the correct lifecycle method for each incomplete function.
import React from 'react';
export class Menu extends React.Component {
constructor(props) {
super(props);
this.state = { items: [] };
}
fetchMenuItems(){
// Menu fetch logic omitted
}
cleanUp(){
// Logic to clean up previous menu items omitted
}
// Fetch menu items when the component loads
componentDidMount() {
this.fetchMenuItems();
}
// Clean up existing menu items and render the new items when an update occurs
// If the content of the component is the same (i.e., props are the same), just return
componentDidUpdate(prevProps) {
if (this.props.cuisine === prevProps.cuisine) {
return;
}
this.cleanUp();
this.fetchMenuItems();
}
// Clean up existing menu items when the component is no longer in use
componentWillUnmount() {
this.cleanUp();
}
render() {
return (
// Render elements omitted
);
}
}
━━━━━━━━━★
Q: What is an advantage of using a platform as a service (PaaS), such as Netlify, to deploy a React.js application? A: Many site configurations are handled, making it possible to focus on building the actual application.
✦•······················•✦•······················•✦
Complete the program below to create a getter called price that returns the value of the ._price property.
Then, using an appropriate method of the Artwork class, set the price of starryNight to 1300.
class Artwork {
constructor(title, artist){
this._title = title;
this._artist = artist;
this._price = 1000;
}
get title(){
return this._title;
}
get artist(){
return this._artist;
}
setPrice(price){
this._price = price;
}
// Add a getter for price
get price() {
return this._price;
}
}
const starryNight = new Artwork('The Starry Night', 'Vincent van Gogh');
// Set the price for starryNight
starryNight.setPrice(1300);
console.log(`${starryNight.title} by ${starryNight.artist} is on sale for $${starryNight.price}!`);
Explanation:
- We added a getter method named
price
to theArtwork
class, which returns the value of the_price
property. - To set the price of
starryNight
, we called thesetPrice()
method on thestarryNight
object, passing the new price as an argument. - Finally, we logged a message to the console displaying the title, artist, and price of the
starryNight
artwork.
━━━━━━━━━★
Create a function called checkPassword()
that takes password as a parameter. Inside the checkPassword()
function, if the length of password is less than 6, throw a new error with the message: 'Password is too short! Generate another password.'.
Lastly, export the generatePassword()
and checkPassword()
functions at the bottom of the code.
If the code works correctly, clicking on the “Generate Password” button should generate a password with a length of 4 to 8 digits. If the generated password length is less than 6, the error message will be displayed.
const generatePassword = () => {
let passwordLength = Math.floor(Math.random() * 5 + 4);
let generatedPassword = Math.floor(Math.random() * Math.pow(10, passwordLength));
return generatedPassword.toString();
}
const checkPassword = (password) => {
if (password.length < 6) {
throw new Error('Password is too short! Generate another password.');
}
}
export { generatePassword, checkPassword };
Explanation:
- We added a function named
checkPassword
that takes password as a parameter. - Inside the
checkPassword
function, we check if the length of the password is less than 6. If it is, we throw a new error with the specified message. - Both the
generatePassword
andcheckPassword
functions are exported using the export keyword.
━━━━━━━━━★
The following tests the functionality of Calculate.factorial()
method. Inside the 'returns the factorial of a number' test, create an assertion for strict equality between result and expectedResult.
Then run mocha test.js
to check that your test passes successfully.
const assert = require("assert");
const Calculate = require('./index.js')
describe('Calculate', () => {
describe('.factorial',() => {
it('returns the factorial of a number', () => {
const expectedResult = 120;
const inputNumber = 5;
const result = Calculate.factorial(inputNumber);
// Create an assertion for strict equality between result and expectedResult
assert.strictEqual(result, expectedResult);
});
});
});
Explanation:
- We used the
assert.strictEqual
method to assert strict equality betweenresult
andexpectedResult
. - This assertion verifies that the
factorial
method returns the correct factorial for the input number.
━━━━━━━━━★
Below is an application that retrieves data from the Datamuse API
.
Modify getSuggestions()
to be an asynchronous function. Then, inside the try statement, use fetch()
to retrieve an API response using the endpoint variable. Make sure the cache parameter is set to 'no-cache'.
If the API call results in a successful response, render the .json() response using renderResponse()
function.
// Information to reach API
const url = 'https://api.datamuse.com/words?';
const queryParams = 'rel_jjb=';
const wordQuery = 'ocean';
// modify getSuggestions to be async
const getSuggestions = async () => {
const endpoint = `${url}${queryParams}${wordQuery}`;
try {
// fetch response from endpoint
const response = await fetch(endpoint, { cache: 'no-cache' });
// if successful response, get json and render using renderResponse() function
if (response.ok) {
const jsonResponse = await response.json();
renderResponse(jsonResponse);
}
} catch (error) {
console.log(error);
}
}
const renderResponse = (res) => {
let responseParagraph = document.getElementById('response');
for(let i = 0; i < 10; i++){
let newP = document.createElement('P');
newP.innerHTML = res[i].word;
responseParagraph.append(newP);
}
}
getSuggestions();
Explanation:
- We made
getSuggestions()
an asynchronous function by adding theasync
keyword before its definition. - Inside the
try
block, we usedfetch()
to retrieve the API response from theendpoint
URL. We specified{ cache: 'no-cache' }
to ensure that the response is not cached. - If the response is successful (status code 200), we used
response.json()
to parse the JSON response and then rendered it using therenderResponse()
function. - In case of any errors, they are caught and logged to the console.
━━━━━━━━━★
Complete the application by doing the following:
- Create a variable called
menuObject
and set it to the result of parsing menu as a JSON object. - Using template literals, log
menuObject
‘sappetizer
,main
, anddessert
to the console.
The console should output the following:
Today's Menu: Appetizer: Shrimp Shumai Main Course: Aloo Gobi Dessert: Key Lime Pie
const menu = '{"appetizer":"Shrimp Shumai","main":"Aloo Gobi","dessert":"Key Lime Pie"}';
// Parse menu as a JSON object
const menuObject = JSON.parse(menu);
console.log('Today\'s Menu:');
// Log appetizer, main, and dessert by referencing properties
console.log(`Appetizer: ${menuObject.appetizer}`);
console.log(`Main Course: ${menuObject.main}`);
console.log(`Dessert: ${menuObject.dessert}`);
Explanation:
- We used
JSON.parse()
to parse themenu
string into a JSON object, storing it in themenuObject
variable. - Then, we logged the menu items (appetizer, main, and dessert) to the console using template literals and referencing the properties of the
menuObject
.
━━━━━━━━━★
The program below is a React.js application that allows users to RSVP to a birthday party. Complete the application by doing the following:
- In the body of the Reserve component, use the hook
useState
to define a state setter constant calledsetReserved
and a state constant calledreserved
, initialized to false. - Change the reserved state on the “RSVP Now!” button click. Toggle the state of reserved
(true -> false or false -> true)
in the body ofreserveEvent()
. - Inside Reserve‘s return statement, render the eventName prop as an
<h2>
element. The prop is being passed in from the parent App component. - Inside Reserve‘s return statement, show
<p>You're set! See you there!</p>
when the reserved state is true.
If the code runs successfully, you should see a button labeled “RSVP Now!” for “Codey’s” birthday party.
import React, { useState } from 'react';
function Reserve(props){
// Create a state constant and set the initial state to `false`
const [reserved, setReserved] = useState(false);
function reserveEvent(){
// Set reserved state to newReservation
setReserved(!reserved);
}
return(
<div className='Reserve'>
{/* Set H2 text to be eventName prop */}
<h2>{props.eventName}</h2>
<button onClick={reserveEvent}>
RSVP Now!
</button>
{reserved && (
<p>You're set! See you there!</p>
)}
</div>
)
}
export default Reserve;
Explanation:
- We use the
useState
hook to define a state variablereserved
and its setter functionsetReserved
, initialized tofalse
. - Inside the
reserveEvent
function, we toggle the state ofreserved
by callingsetReserved(!reserved)
. - In the return statement, we render the
eventName
prop passed from the parentApp
component as an<h2>
element. - We use the
reserved
state to conditionally render the message "You're set! See you there!" whenreserved
istrue
.
━━━━━━━━━★
The rendered React application should display a clock for various time zones. Right now, the clock is stuck on the initially rendered time and we’d like to use intervals to update the time. In Clock.js
, a Clock component is defined with functions called createInterval()
and cleanUpInterval()
. Use these functions to fix the application by doing the following:
- Create an effect that executes on the first render and any changes to the timezone prop.
- Pass an inline function as the first argument to the effect which should call
createInterval()
and store the returned value in a constant calledintervalId
. - The effect function should clean up the previous
intervalId
before callingcreateInterval()
when it re-executes due to changes to the timezone prop. CallcleanUpInterval()
withintervalId
as an argument and return its value.
import React, { useState, useEffect } from 'react';
function Clock(props){
const [date, setDate] = useState(new Date());
function createInterval() {
const delay = 1000;
return setInterval(() => {
setDate(new Date());
}, delay)
}
function cleanUpInterval(id) {
return () => clearInterval(id);
}
useEffect(() => {
// Call createInterval and store the intervalId in a constant
const intervalId = createInterval();
// Return a clean-up function that clears the interval
return cleanUpInterval(intervalId);
}, [props.timezone]); // Execute the effect when the timezone prop changes
return (
<div>
<p className='clock-text'>{date.toLocaleTimeString('en-us', {'timeZone': props.timezone})}</p>
<p className='timezone-text'>{props.timezone}</p>
</div>
);
}
export default Clock;
Explanation:
- We use the
useEffect
hook to create an effect that runs when the component first renders and whenever the timezone prop changes. - Inside the effect, we call
createInterval()
to start an interval timer that updates the time every second. - We store the returned interval ID in a constant
intervalId
. - We return a clean-up function that clears the interval using
cleanUpInterval(intervalId)
. - The effect will clean up the previous interval and start a new one whenever the timezone prop changes.
━━━━━━━━━★
The below application is a React.js application that renders a Chocolate Chip Cookies Recipe. The application has a button that should switch the measurements of the ingredients between ounces (oz) and grams (g).
Complete the application by creating an effect hook that triggers when the value of unit changes. The effect hook should check the value of unit and set the amount value of the recipe state to the converted values using the new unit:
If the unit is 'g', the value of amount should be converted using the ozToG()
function.
If the unit is 'oz', the value of amount should be converted using the gToOz()
function.
import React, { useState, useEffect } from 'react';
function Recipe(props) {
const { unit } = props;
const [recipe, setRecipe] = useState([
{ name: 'Salted Butter', amount: 250 },
{ name: 'Granulated Sugar', amount: 200 },
{ name: 'Milk', amount: 100 },
{ name: 'All-Purpose Flour', amount: 360 },
{ name: 'Chocolate Chips', amount: 350 }
]);
const gToOz = (value) => {
return (value / 28.35).toFixed(2);
};
const ozToG = (value) => {
return (value * 28.35).toFixed(0);
};
useEffect(() => {
// Calculate the new amounts based on the unit
const newRecipe = recipe.map(item => {
if (unit === 'g') {
return { ...item, amount: ozToG(item.amount) };
} else if (unit === 'oz') {
return { ...item, amount: gToOz(item.amount) };
}
return item;
});
// Update the recipe state with the new amounts
setRecipe(newRecipe);
}, [unit]); // Trigger the effect when the unit changes
return (
<div className='ingredient-list'>
{recipe.map((item, i) => (
(<p key={i}><span className='name'>{item.name}</span>: {item.amount}{unit}</p>)
))}
</div>
);
}
export default Recipe;
Explanation:
- We use the
useEffect
hook to create an effect that runs whenever theunit
prop changes. - Inside the effect, we calculate the new amounts for each ingredient based on the new unit using the
gToOz()
andozToG()
functions. - We map over the current list of ingredients (
recipe
) and update each item's amount accordingly based on the new unit. - Finally, we update the
recipe
state with the new amounts.
━━━━━━━━━★
The following application is the start of an application that renders a restaurant menu item and allows users to select the item quantity and add it to their cart. Complete the application by doing the following:
- At the top of the file, import
useSelector()
anduseDispatch()
hooks fromreact-redux
. - At the top of the
Counter
component, create a variable calledcount
and set it to auseSelector()
hook forselectCount
. - Next, create a variable called
dispatch
and set it to auseDispatch()
hook. - Dispatch appropriate actions when the “+” and “-“ buttons are clicked:
- The “+” button with
.add-btn
class should dispatchincrement()
on click. - The “-“ button with
.remove-btn
class should dispatchdecrement()
on click.
If the application works correctly, you should be able to add and remove an item quantity. When you click the “Add To Cart” button, you should see an alert window telling you how many items were added to the cart.
import React from 'react';
import { useSelector, useDispatch } from 'react-redux'; // Importing useSelector() and useDispatch() hooks from react-redux
import {
decrement,
increment,
selectCount,
} from './counterSlice';
function Counter() {
const count = useSelector(selectCount); // Using useSelector() hook for selectCount and setting it to a variable called count
const dispatch = useDispatch(); // Using useDispatch() hook and setting it to a variable called dispatch
return (
<div>
<div className='item-counter'>
<button className='remove-btn' aria-label="Decrement value" onClick={() => dispatch(decrement())}>
- {/* Dispatching decrement() on click */}
</button>
<span className='counter-text'>{count}</span>
<button className='add-btn' aria-label="Increment value" onClick={() => dispatch(increment())}>
+ {/* Dispatching increment() on click */}
</button>
</div>
<div className='add-to-cart'>
<button className='add-to-cart-btn' onClick={() => alert(`Added ${count} items to the cart!`)}>
Add To Cart
</button>
</div>
</div>
);
}
export default Counter;
Explanation:
- We use the
useSelector
hook to select thecount
state from the Redux store and store it in thecount
variable. - We use the
useDispatch
hook to get thedispatch
function, which we'll use to dispatch actions to the Redux store. - When the "+" button is clicked, we dispatch the
increment()
action. - When the "-" button is clicked, we dispatch the
decrement()
action. - When the "Add To Cart" button is clicked, we display an alert with the number of items added to the cart.
━━━━━━━━━★ ━━━━━━━━━★