fix(curriculum): react code block identifier (#60764)

Co-authored-by: Huyen Nguyen <25715018+huyenltnguyen@users.noreply.github.com>
This commit is contained in:
Aishwarya
2025-06-12 17:27:24 +05:30
committed by GitHub
parent f09732fdc6
commit 98e689e2e0
24 changed files with 285 additions and 287 deletions
@@ -24,7 +24,7 @@ This UI is described using JSX, a syntax extension for JavaScript that looks sim
Let's look at an example of a React component:
```js
```jsx
function Greeting() {
const name = "John"
{/* The result will be Hello John*/}
@@ -42,7 +42,7 @@ Well, this is because in JavaScript, `class` is a reserved name. So, we need to
We are also using a comment in JSX showing what the result will be. It is important to note that you can use regular comment syntax like this but it needs to be wrapped in curly braces in order for it to work:
```js
```jsx
{/* Block Comments */}
```
@@ -54,7 +54,7 @@ When React encounters a lowercase tag, like `<div>` or `<span>`, it assumes it's
To use this `Greeting` component in our application, we would write something like this:
```js
```jsx
<Greeting />
```
@@ -62,7 +62,7 @@ This would render an `h1` element with the text `Hello John` to the page. But ta
When working with JSX, all tags and uses of components need to be explicitly closed. So if the component or tag does not have any children, then you need to explicitly close it like shown here:
```js
```jsx
<Greeting /> {/* /> is required */}
```
@@ -70,7 +70,7 @@ So far we have only been looking at how to render a single `h1` element. But you
Lets take a look at the following example code here:
```js
```jsx
function Greeting() {
const name = "John";
{/* This will throw an error */}
@@ -87,7 +87,7 @@ The reason why you are getting that error message is because multiple sibling el
React fragments are used to group elements together. Here is what the revised example will look like:
```js
```jsx
function Greeting() {
const name = "John";
return (
@@ -101,7 +101,7 @@ function Greeting() {
You can also choose to use empty JSX tags which can serve as shorthand for fragments:
```js
```jsx
function Greeting() {
const name = "John";
return (
@@ -20,7 +20,7 @@ In this example, we have a `Cat` component that belongs in a file called `Cat.js
This `Cat` component returns a JSX markup with a title and image for a cat called Mr. Whiskers:
```js
```jsx
function Cat() {
return (
<div className="card">
@@ -36,7 +36,7 @@ function Cat() {
If we want to use our `Cat` component in another file, we need to first export it like this:
```js
```jsx
function Cat() {
return (
<div className="card">
@@ -54,7 +54,7 @@ export default Cat;
We are using the `default` keyword because this will be the default export from the module. You can also choose to export the component on the same line as the component definition like this:
```js
```jsx
export default function Cat() {
return (
<div className="card">
@@ -72,7 +72,7 @@ You can choose to import child components in other parent component files, or im
Every React project will have a top-level component, typically called `App.jsx`:
```js
```jsx
export default function App() {
return (
// return component here
@@ -84,7 +84,7 @@ This file is usually located in the `src` directory of your project. Youll le
To use the `Cat` component inside the root `App` component, you will need to import it like this:
```js
```jsx
import Cat from "./Cat";
export default function App() {
@@ -96,7 +96,7 @@ export default function App() {
Now, you can return the `Cat` component inside the `App` component like this:
```js
```jsx
import Cat from "./Cat";
export default function App() {
@@ -116,7 +116,7 @@ Which of the following is the correct way to export a React component?
## --answers--
```js
```jsx
export default function Cat() {
return (
<div className="card">
@@ -132,7 +132,7 @@ export default function Cat() {
---
```js
```jsx
exportComponent function Cat() {
return (
<div className="card">
@@ -152,7 +152,7 @@ Review the middle of the video where this was discussed.
---
```js
```jsx
e.default function Cat() {
return (
<div className="card">
@@ -172,7 +172,7 @@ Review the middle of the video where this was discussed.
---
```js
```jsx
default function Cat() {
return (
<div className="card">
@@ -38,7 +38,7 @@ If you check the `package.json` file, you will see that `react-router` was added
Then inside of your `main.jsx` or `index.jsx` file, you will need to import `BrowserRouter` and render `BrowserRouter` around your `App` component:
```js
```jsx
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { BrowserRouter } from "react-router";
@@ -63,7 +63,7 @@ import { BrowserRouter, Routes, Route } from "react-router";
Then inside of the `BrowserRouter`, add the `Routes` and `Route` components:
```js
```jsx
createRoot(document.getElementById("root")).render(
<StrictMode>
<BrowserRouter>
@@ -79,7 +79,7 @@ The `path` and `element` are used to couple the URL and UI components together.
It is common in larger applications to have multiple views and routes setup like this:
```js
```jsx
<Routes>
<Route index element={<Home />} />
<Route path="about" element={<About />} />
@@ -97,7 +97,7 @@ The `index` prop in these examples is meant to represent the default route for a
You may have also noticed that we are nesting a few routes inside another route like this:
```js
```jsx
<Route path="products">
<Route path="trending" element={<Trending />} />
</Route>
@@ -107,7 +107,7 @@ This means that the path of the child route will be appended to the parent route
If the `path` begins with a colon (`:`) then that represents a dynamic segment in the route:
```js
```jsx
<Route path=":category" element={<Category />} />
```
@@ -115,7 +115,7 @@ In this example we have a dynamic segment called `category`. When a user navigat
You can access the value of the dynamic segment by using the `useParams` hook inside the child component like this:
```js
```jsx
import { useParams } from "react-router";
export default function Category() {
@@ -39,7 +39,7 @@ Another feature of Next.js are the automatic image and font optimizations.
Here is an example of working with the `Image` component inside a `page.js` file:
```js
```jsx
import Image from "next/image";
export default function Page() {
@@ -36,7 +36,7 @@ const sectionRef = useRef(null);
The final thing to do is to attach the ref variable to the element in your JSX by using the `ref` attribute:
```js
```jsx
<section ref={sectionRef}>
{/* Section content */}
</section>
@@ -64,7 +64,7 @@ A typical example to showcase a ref is to focus an input element on render, or b
Here's how to do that when you click a button:
```js
```jsx
import { useRef } from "react";
const Focus = () => {
@@ -32,7 +32,7 @@ Then you use it as a function, like this:
```js
useEffect(() => {
// Your side effect logic (usually a function) here
// Your side effect logic (usually a function) here
}, [dependencies]);
```
@@ -48,7 +48,7 @@ Note that `dependencies` can be an array of "reactive values" (state, props, fun
For example, in this `Counter` application, we don't pass in a `dependencies` argument, so the effect runs when the component renders and every time it updates:
```js
```jsx
import { useState, useEffect } from "react";
const Counter = () => {
@@ -103,10 +103,10 @@ Here's the syntax for returning a cleanup function from the `useEffect` hook:
```js
useEffect(() => {
// Your side effect logic here
return () => {
// Cleanup logic here (optional)
};
// Your side effect logic here
return () => {
// Cleanup logic here (optional)
};
}, [dependencies]);
```
@@ -80,20 +80,20 @@ To use this hook, we've prepared a `footballers` array to filter through with a
```js
const footballers = [
'Lionel Messi', 'Cristiano Ronaldo', 'Neymar Jr',
'Kylian Mbappe', 'Mohamed Salah', 'Sadio Mane',
'Kevin De Bruyne', 'Robert Lewandowski', 'Harry Kane',
'Sergio Ramos', 'Virgil van Dijk', 'Alisson Becker',
'Joshua Kimmich', 'Manuel Neuer', 'Karim Benzema',
'Thibaut Courtois', 'Eden Hazard', 'Raheem Sterling',
'Bruno Fernandes', 'Trent Alexander-Arnold', 'Son Heung-min',
'Pierre-Emerick Aubameyang','Sergio Aguero', 'Luis Suarez',
'Luka Modric', 'Casemiro', 'Frenkie de Jong', 'Gerard Pique',
'Marc-Andre ter Stegen', 'Keylor Navas', 'Angel Di Maria',
"N'Golo Kante", 'Kai Havertz', 'Timo Werner', 'Hakim Ziyech',
'Christian Pulisic', 'Mason Mount', 'Olivier Giroud', 'Tammy Abraham',
'Kepa Arrizabalaga', 'Ben Chilwell', 'Thiago Silva', 'Kurt Zouma',
'John Terry', 'Didier Drogba', 'Frank Lampard', 'Ashley Cole', 'Petr Cech',
'Lionel Messi', 'Cristiano Ronaldo', 'Neymar Jr',
'Kylian Mbappe', 'Mohamed Salah', 'Sadio Mane',
'Kevin De Bruyne', 'Robert Lewandowski', 'Harry Kane',
'Sergio Ramos', 'Virgil van Dijk', 'Alisson Becker',
'Joshua Kimmich', 'Manuel Neuer', 'Karim Benzema',
'Thibaut Courtois', 'Eden Hazard', 'Raheem Sterling',
'Bruno Fernandes', 'Trent Alexander-Arnold', 'Son Heung-min',
'Pierre-Emerick Aubameyang','Sergio Aguero', 'Luis Suarez',
'Luka Modric', 'Casemiro', 'Frenkie de Jong', 'Gerard Pique',
'Marc-Andre ter Stegen', 'Keylor Navas', 'Angel Di Maria',
"N'Golo Kante", 'Kai Havertz', 'Timo Werner', 'Hakim Ziyech',
'Christian Pulisic', 'Mason Mount', 'Olivier Giroud', 'Tammy Abraham',
'Kepa Arrizabalaga', 'Ben Chilwell', 'Thiago Silva', 'Kurt Zouma',
'John Terry', 'Didier Drogba', 'Frank Lampard', 'Ashley Cole', 'Petr Cech',
];
export default footballers;
@@ -101,7 +101,7 @@ export default footballers;
And here's a `FootballerSearch` component that uses the `useDebounce` hook to delay searching for 1 second after the user stops typing:
```js
```jsx
import { useState, useEffect } from "react";
import { useDebounce } from "./hooks/useDebounce";
import footballers from "./footballers";
@@ -88,7 +88,7 @@ You can then go ahead and use all of those states to render the data from the AP
Here's the full code:
```js
```jsx
import { useState, useEffect } from "react";
const FetchPosts = () => {
@@ -209,34 +209,34 @@ Note that the "fetcher" name here is only a convention, so you're free to name t
Here's a component fetching todos from the JSON Placeholder API:
```js
```jsx
import useSWR from "swr";
const fetcher = (url) => fetch(url).then((res) => res.json());
const FetchTodos = () => {
const { data, error } = useSWR(
"https://jsonplaceholder.typicode.com/todos",
fetcher
);
const { data, error } = useSWR(
"https://jsonplaceholder.typicode.com/todos",
fetcher
);
if (!data) {
return <h2>Loading...</h2>;
}
if (error) {
return <h2>Error: {error.message}</h2>;
}
if (!data) {
return <h2>Loading...</h2>;
}
if (error) {
return <h2>Error: {error.message}</h2>;
}
return (
<>
<h2>Todos</h2>
<div>
{data.map((todo) => (
<h3 key={todo.id}>{todo.title}</h3>
))}
</div>
</>
);
return (
<>
<h2>Todos</h2>
<div>
{data.map((todo) => (
<h3 key={todo.id}>{todo.title}</h3>
))}
</div>
</>
);
};
export default FetchTodos;
@@ -246,19 +246,19 @@ As you learned in a previous lecture on custom hooks, data fetching is a logic y
Here's a `useFetch` hook that uses SWR for data fetching:
```js
```jsx
import useSWR from "swr";
const fetcher = (url) => fetch(url).then((res) => res.json());
const useFetch = (url) => {
const { data, error } = useSWR(url, fetcher);
const { data, error } = useSWR(url, fetcher);
return {
data,
loading: !data && !error,
error,
};
return {
data,
loading: !data && !error,
error,
};
};
export default useFetch;
@@ -266,32 +266,32 @@ export default useFetch;
And here's how to use the `useFetch` hook to rewrite the first example that fetches posts from the JSON Placeholder API:
```js
```jsx
import useFetch from "./useFetch";
const FetchPosts = () => {
const { data, loading, error } = useFetch(
"https://jsonplaceholder.typicode.com/posts"
);
const { data, loading, error } = useFetch(
"https://jsonplaceholder.typicode.com/posts"
);
if (loading) {
return <h2>Loading...</h2>;
}
if (loading) {
return <h2>Loading...</h2>;
}
if (error) {
return <h2>{error.message}</h2>;
}
if (error) {
return <h2>{error.message}</h2>;
}
return (
<>
<h2>Posts</h2>
<ul>
{data.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</>
);
return (
<>
<h2>Posts</h2>
<ul>
{data.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</>
);
};
export default FetchPosts;
@@ -48,10 +48,10 @@ Let's see how to use the `useMemo` hook first. Here's the basic syntax of the `u
```js
const memoizedValue = useMemo(
function () {
return computeExpensiveValue(a, b);
},
[a, b]
function () {
return computeExpensiveValue(a, b);
},
[a, b]
);
```
@@ -59,26 +59,26 @@ You can see all that's needed is to wrap the `useMemo` hook around the function.
This `ExpensiveSquare` component will receive a `num` prop which it will use to calculate the square:
```js
```jsx
function ExpensiveSquare({ num }) {
function calculateSquare(n) {
console.log("Calculating square...");
return n * n;
}
function calculateSquare(n) {
console.log("Calculating square...");
return n * n;
}
const squared = calculateSquare(num);
return (
<p>
Square of {num}: {squared}
</p>
);
const squared = calculateSquare(num);
return (
<p>
Square of {num}: {squared}
</p>
);
}
export default ExpensiveSquare;
```
Here's the `App` component where the `ExpensiveSquare` is being used:
```js
```jsx
import { useState, useEffect } from "react";
import ExpensiveSquare from "./components/ExpensiveSquare";
@@ -107,7 +107,7 @@ The `timer` in the `useEffect`, running every second, will make the `calculateSq
To solve this problem, we can use the `useMemo` hook by wrapping the function call in it and specifying the `num` variable as the dependency:
```js
```jsx
// import the useMemo hook
import { useMemo } from "react";
@@ -32,7 +32,7 @@ const handleClick = useCallback(() => {
And here's the basic syntax of `React.memo`:
```js
```jsx
const MemoizedComponent = React.memo(({ prop }) => {
return (
<>
@@ -44,7 +44,7 @@ const MemoizedComponent = React.memo(({ prop }) => {
Let's look at an example of the `useCallback` hook:
```js
```jsx
import { useState, useEffect } from "react";
function Counter() {
@@ -73,7 +73,7 @@ In the component, the effect runs any time `handleClick` changes because the `ha
To fix this, you need to tell React to treat the `handleClick` function as the same thing across renders by memoizing it with the `useCallback` hook, so it doesn't get recreated:
```js
```jsx
import { useState, useEffect, useCallback } from "react";
function Counter() {
@@ -103,7 +103,7 @@ Now the `handleClick` function is not being recreated on every render.
To show you how the `React.memo` (or `memo`) higher-order function works and the `useCallback` hook work in tandem, here's a `Counter` component with a `handleClick` function that needs `useCallback` but is currently not using it:
```js
```jsx
import { useState, useEffect, useCallback } from "react";
import CounterChild from "./CounterChild";
@@ -142,7 +142,7 @@ That's why the `handleClick` needs to be memoized with `useCallback`.
Here's the `CounterChild` component:
```js
```jsx
const CounterChild = ({ onClick }) => {
console.log("CounterChild component rendered");
return <button onClick={onClick}>Increment from Child</button>;
@@ -159,7 +159,7 @@ Without memoization, because as the component re-renders due to the timer updati
To prevent this, you need to memoize the `CounterChild` component with `React.memo`:
```js
```jsx
import React from "react";
const CounterChild = React.memo(({ onClick }) => {
@@ -246,7 +246,7 @@ The second argument should be an array of dependencies.
---
```js
```jsx
const handleClick = useCallback(() => { /* code */ }, [dependency]);
```
@@ -58,7 +58,7 @@ export async function saveTask(task) {
Here's the code that sets up the `useOptimistic` hook by importing and initializing it, with an `handleSubmit` function that sends an input to the action:
```js
```jsx
"use client";
import { useOptimistic } from "react";
@@ -91,7 +91,7 @@ When the form is submitted, the `handleSubmit` function extracts the task and ad
Here's the `TaskList` component:
```js
```jsx
"use client";
import { useOptimistic, startTransition } from "react";
@@ -150,7 +150,7 @@ Here, we are looping through the `optimisticTask` parameter to display the task.
Here's the `Task` component that manages the state for the form. It calls the `saveTask` function from the action so it can add the task, and appends the new task once it is received by the server:
```js
```jsx
"use client";
import { useState } from "react";
@@ -16,7 +16,7 @@ How do you pass props from a parent component to a child component in react?
In the previous lectures, we learned how to build small components in React like this:
```js
```jsx
function Greeting() {
const developerName = "Jessica";
return <h1>Hi {developerName}!</h1>;
@@ -25,7 +25,7 @@ function Greeting() {
We can choose to nest this component inside another parent component or the root component like this:
```js
```jsx
function App() {
return <Greeting />;
}
@@ -42,7 +42,7 @@ What if we wanted to display a different name like Naomi, Tom, or Oliver? This i
Let's update our example from earlier to now accept a `name` prop:
```js
```jsx
function App() {
return <Greeting name="Jessica" />;
}
@@ -61,7 +61,7 @@ Then, inside of the parent `App` component, we are passing the value to the `nam
Now we have the ability to reuse the child component several times and pass in different names each time:
```js
```jsx
function App() {
return (
<>
@@ -76,7 +76,7 @@ function App() {
You can also choose to use object destructuring in the props to make it more readable. Here's how you could rewrite the `Greeting` component:
```js
```jsx
function Greeting({ name }) {
return <h1>Hi {name}!</h1>;
}
@@ -88,7 +88,7 @@ Sometimes, you can have a lot of properties that you have to pass as props. Inst
Here is an example of a new child component called `DeveloperCard`:
```js
```jsx
function DeveloperCard({ name, age, country }) {
return (
<div className="developer-card">
@@ -104,7 +104,7 @@ This `DeveloperCard` component accepts three props: `name`, `age`, and `country`
In the parent `App` component, we can use the spread syntax to pass all the properties from an object as individual props to the child component:
```js
```jsx
function App() {
const developerObj = {
name: "Alice",
@@ -20,7 +20,7 @@ The most common approaches of using conditional rendering includes using `if` st
The simplest form of conditional rendering uses an `if` statement. Here's an example:
```js
```jsx
function Greeting({ isLoggedIn }) {
if (isLoggedIn) {
return <h1>Welcome back!</h1>;
@@ -33,7 +33,7 @@ In this example, the `Greeting` component checks the `isLoggedIn` prop. If it's
Here is an example using the `Greeting` component inside of the parent `App` component:
```js
```jsx
function App() {
return (
<div className="App">
@@ -45,7 +45,7 @@ function App() {
For simpler conditions, the ternary operator (`?:`) is often used directly within JSX. It allows for inline conditional rendering, which can make your code more concise:
```js
```jsx
function Greeting({ isLoggedIn }) {
return <h1>{isLoggedIn ? "Welcome back!" : "Please sign in."}</h1>;
}
@@ -55,7 +55,7 @@ This code achieves the same result as the previous example but in a more compact
Another common pattern for conditional rendering is using the logical AND (`&&`) operator. This is particularly useful when you want to render something, or nothing, based on a condition:
```js
```jsx
function Notification({ message }) {
return (
<div>
@@ -111,7 +111,7 @@ Using the `switch` statement.
What will be rendered by the following code if `message` is an empty string?
```js
```jsx
function Alert({ message }) {
return (
<div>
@@ -157,7 +157,7 @@ Consider how the logical AND (`&&`) operator works with falsy values in JSX.
In the following code, what type of conditional rendering is being used?
```js
```jsx
function Greeting({ name }) {
return <h1>{name ? `Hello, ${name}!` : 'Hello, Guest!'}</h1>;
}
@@ -18,7 +18,7 @@ Rendering lists is a fundamental task in React web apps, and is used for display
Here is an example of a component called `FruitList` that displays a list of fruits:
```js
```jsx
function FruitList() {
const fruits = ['Apple', 'Banana', 'Cherry', 'Date'];
return (
@@ -35,7 +35,7 @@ However, when rendering lists in React, it is important not to forget the `key`
Let's modify our example to include keys:
```js
```jsx
function FruitList() {
const fruits = ["Apple", "Banana", "Cherry", "Date"];
return (
@@ -52,7 +52,7 @@ In this refactored example, we are creating a unique key for each list item by c
React also allows you to render more complex structures. For instance, you might have an array of objects representing users, each with multiple properties that you want to display:
```js
```jsx
function UserList() {
const users = [
{ id: "user-001-employee", name: "Alice", email: "alice@example.com" },
@@ -20,7 +20,7 @@ React's approach to inline styles involves using JavaScript objects to define st
Here is an example of how you can use inline styles for a `Button` component:
```js
```jsx
function Button({ buttonText }) {
const defaultStyles = {
backgroundColor: "#007BFF",
@@ -42,7 +42,7 @@ In this example, we define a style object called `defaultStyles`. We then apply
You can also choose to pass in an object directly to the `style` attribute. Here is what a revised example would look like:
```js
```jsx
function Button({ buttonText }) {
return (
<button
@@ -63,7 +63,7 @@ It's important to note that while CSS property names are typically written in ke
A great advantage of inline styles in React is that they support dynamic styling based on a component state or props. For example:
```js
```jsx
function DynamicButton({ isActive }) {
const buttonStyles = {
backgroundColor: isActive ? "green" : "red",
@@ -24,7 +24,7 @@ Controlled input is the most "React-like" way to handle form inputs. With contro
The process works like this: React maintains the form state with the `useState` hook, and you update it on every change. When a user types in an input field, the `onChange` event fires, updates the state, and React re-renders the component with the new value.
```js
```jsx
import { useState } from "react";
function App() {
@@ -69,24 +69,24 @@ Since the DOM controls the input values, what you need is to pull in the values
Here's an example of uncontrolled inputs:
```js
```jsx
import { useRef } from "react";
function App() {
const nameRef = useRef();
const nameRef = useRef();
const handleSubmit = (e) => {
e.preventDefault();
console.log(nameRef.current.value);
};
const handleSubmit = (e) => {
e.preventDefault();
console.log(nameRef.current.value);
};
return (
<form onSubmit={handleSubmit}>
<label htmlFor="name">Your</label>{" "}
<input type="text" ref={nameRef} id="name" />
<button type="submit">Submit</button>
</form>
);
return (
<form onSubmit={handleSubmit}>
<label htmlFor="name">Your</label>{" "}
<input type="text" ref={nameRef} id="name" />
<button type="submit">Submit</button>
</form>
);
}
export default App;
@@ -26,8 +26,8 @@ A server action looks like this:
"use server";
async function submitForm(formData) {
const name = formData.get("name");
return { message: `Hello, ${name}!` };
const name = formData.get("name");
return { message: `Hello, ${name}!` };
}
```
@@ -67,26 +67,26 @@ To use the `useActionState` hook, make sure you have an action in place first. L
"use server";
export async function submitForm(_, formData) {
const name = formData.get("name");
const name = formData.get("name");
const hour = new Date().getHours();
let greeting;
const hour = new Date().getHours();
let greeting;
if (hour < 12) {
greeting = "Good morning";
} else if (hour < 18) {
greeting = "Good afternoon";
} else {
greeting = "Good evening";
}
if (hour < 12) {
greeting = "Good morning";
} else if (hour < 18) {
greeting = "Good afternoon";
} else {
greeting = "Good evening";
}
return { message: `${greeting}, ${name}` };
return { message: `${greeting}, ${name}` };
}
```
In your component, you then need to import the `useActionState` hook and call it at the top level of the component body (before the return statement) just like other hooks. You should also import the action:
```js
```jsx
"use client";
// Import the useActionState hook
@@ -102,11 +102,11 @@ const Greeter = () => {
message: "",
});
return (
<div className="flex flex-col items-center justify-center min-h-screen bg-gray-100 p-6">
{/* Rest of component */}
</div>
);
return (
<div className="flex flex-col items-center justify-center min-h-screen bg-gray-100 p-6">
{/* Rest of component */}
</div>
);
};
export default Greeter;
@@ -114,51 +114,51 @@ export default Greeter;
Here's what the full code looks like with a bit of styling:
```js
```jsx
"use client";
import { useActionState } from "react";
import { submitForm } from "./actions/submitForm";
const Greeter = () => {
const [state, submit, isPending] = useActionState(submitForm, {
message: "",
});
const [state, submit, isPending] = useActionState(submitForm, {
message: "",
});
return (
<div className="flex flex-col items-center justify-center min-h-screen bg-gray-100 p-6">
<form
action={submit}
className="bg-white p-6 rounded-2xl shadow-md w-full max-w-md"
>
<h2 className="text-2xl text-center font-semibold text-gray-700 mb-4">
Greet Someone
</h2>
return (
<div className="flex flex-col items-center justify-center min-h-screen bg-gray-100 p-6">
<form
action={submit}
className="bg-white p-6 rounded-2xl shadow-md w-full max-w-md"
>
<h2 className="text-2xl text-center font-semibold text-gray-700 mb-4">
Greet Someone
</h2>
<input
type="text"
name="name"
placeholder="Enter your name"
required
className="w-full p-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-green-400"
/>
<input
type="text"
name="name"
placeholder="Enter your name"
required
className="w-full p-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-green-400"
/>
<button
type="submit"
disabled={isPending}
className="w-full mt-4 p-3 bg-green-500 text-white font-semibold rounded-lg hover:bg-green-600 disabled:bg-gray-400 transition-all"
>
{isPending ? "Greeting..." : "Greet"}
</button>
<button
type="submit"
disabled={isPending}
className="w-full mt-4 p-3 bg-green-500 text-white font-semibold rounded-lg hover:bg-green-600 disabled:bg-gray-400 transition-all"
>
{isPending ? "Greeting..." : "Greet"}
</button>
{state.message && (
<p className="mt-4 text-green-600 text-center font-medium">
{state.message}
</p>
)}
</form>
</div>
);
{state.message && (
<p className="mt-4 text-green-600 text-center font-medium">
{state.message}
</p>
)}
</form>
</div>
);
};
export default Greeter;
@@ -174,44 +174,44 @@ In this example, we'll fetch five users from JSONPlaceholder with a button click
"use server";
export async function getUsers() {
const res = await fetch(
"https://jsonplaceholder.typicode.com/users?_start=0&_limit=5/"
);
return await res.json();
const res = await fetch(
"https://jsonplaceholder.typicode.com/users?_start=0&_limit=5/"
);
return await res.json();
}
```
Here's the styled UI:
```js
```jsx
"use client";
import { useActionState } from "react";
import { getUsers } from "./actions/getUsers";
export default function FetchUsers() {
const [users, fetchAction, isPending] = useActionState(getUsers, []);
const [users, fetchAction, isPending] = useActionState(getUsers, []);
return (
<div className="p-6 max-w-lg mx-auto">
<button
onClick={fetchAction}
disabled={isPending}
className="px-4 py-2 cursor-pointer bg-green-500 text-white rounded-lg hover:bg-green-600 disabled:bg-gray-400 font-bold"
>
{isPending ? "Fetching Users..." : "Fetch Users"}
</button>
return (
<div className="p-6 max-w-lg mx-auto">
<button
onClick={fetchAction}
disabled={isPending}
className="px-4 py-2 cursor-pointer bg-green-500 text-white rounded-lg hover:bg-green-600 disabled:bg-gray-400 font-bold"
>
{isPending ? "Fetching Users..." : "Fetch Users"}
</button>
<ul className="mt-4 space-y-2">
{users.map((user) => (
<li key={user.id} className="p-3 bg-gray-100 rounded-lg">
<p className="font-semibold">{user.name}</p>
<p className="text-sm text-gray-600">{user.email}</p>
</li>
))}
</ul>
</div>
);
<ul className="mt-4 space-y-2">
{users.map((user) => (
<li key={user.id} className="p-3 bg-gray-100 rounded-lg">
<p className="font-semibold">{user.name}</p>
<p className="text-sm text-gray-600">{user.email}</p>
</li>
))}
</ul>
</div>
);
}
```
@@ -221,7 +221,7 @@ This happens because React treats data fetching and rendering as a higher priori
To fix this issue, you need to wrap the action in `startTransition`:
```js
```jsx
"use client";
import { useActionState } from "react";
@@ -231,29 +231,29 @@ import { getUsers } from "./actions/getUsers";
import { startTransition } from "react";
export default function FetchUsers() {
const [users, fetchAction, isPending] = useActionState(getUsers, []);
const [users, fetchAction, isPending] = useActionState(getUsers, []);
return (
<div className="p-6 max-w-lg mx-auto">
<button
{/* wrap fetchAction in startTransition */}
onClick={() => startTransition(() => fetchAction())}
disabled={isPending}
className="px-4 py-2 bg-green-500 font-bold cursor-pointer text-white rounded-lg hover:bg-green-600 disabled:bg-gray-400"
>
{isPending ? 'Fetching Users...' : 'Fetch Users'}
</button>
return (
<div className="p-6 max-w-lg mx-auto">
<button
{/* wrap fetchAction in startTransition */}
onClick={() => startTransition(() => fetchAction())}
disabled={isPending}
className="px-4 py-2 bg-green-500 font-bold cursor-pointer text-white rounded-lg hover:bg-green-600 disabled:bg-gray-400"
>
{isPending ? 'Fetching Users...' : 'Fetch Users'}
</button>
<ul className="mt-4 space-y-2">
{users.map((user) => (
<li key={user.id} className="p-3 bg-gray-100 rounded-lg">
<p className="font-semibold">{user.name}</p>
<p className="text-sm text-gray-600">{user.email}</p>
</li>
))}
</ul>
</div>
);
<ul className="mt-4 space-y-2">
{users.map((user) => (
<li key={user.id} className="p-3 bg-gray-100 rounded-lg">
<p className="font-semibold">{user.name}</p>
<p className="text-sm text-gray-600">{user.email}</p>
</li>
))}
</ul>
</div>
);
}
```
@@ -90,7 +90,7 @@ In the code above, we have the `useState` hook imported from React. In the `Coun
You can manage multiple pieces of state by calling the `useState` hook multiple times. This is especially important when you have unrelated state variables:
```js
```jsx
function UserProfile() {
const [isOnline, setIsOnline] = useState(false);
const [notifications, setNotifications] = useState(0);
@@ -101,7 +101,7 @@ function UserProfile() {
You can also call the `useState` hook multiple times when managing multiple states that update separately, like form fields:
```js
```jsx
function SignUpForm() {
const [name, setName] = useState("");
const [username, setUsername] = useState("");
@@ -113,7 +113,7 @@ function SignUpForm() {
But in this case, it's best to combine the states since they're all part of the same form:
```js
```jsx
function SignUpForm() {
const [formData, setFormData] = useState({
name: "",
@@ -249,7 +249,7 @@ Review the end of the video where the answer was discussed.
---
```js
```jsx
const [formData, setFormData] = useState({
name: "",
username: "",
@@ -167,31 +167,31 @@ Which of the following is NOT a valid attribute used for handling React events?
Which of the following is the correct way to update array state?
```jsx
```js
const [certificates, setCertificates] = useState([]);
```
#### --distractors--
```jsx
```js
setCertificates(previousItems => previousItems, "Front End");
```
---
```jsx
```js
setCertificates.push("Front End");
```
---
```jsx
```js
setCertificates().append("Front End");
```
#### --answer--
```jsx
```js
setCertificates(previousItems => [...previousItems, "Front End"]);
```
@@ -201,7 +201,7 @@ setCertificates(previousItems => [...previousItems, "Front End"]);
What is wrong with this function?
```jsx
```js
function updateSpaceship() {
setSpaceship(previousState => ({
name: "Discovery"
@@ -325,7 +325,7 @@ inputRef.current
How many times will this message be logged to the console?
```jsx
```js
useEffect(() => {
console.log("Nice work!!");
}, []);
@@ -556,7 +556,7 @@ What is the purpose of the `dependencies` in a `useEffect`?
```js
useEffect(() => {
// Your side effect logic (usually a function) goes here
// Your side effect logic (usually a function) goes here
}, [dependencies]);
```
@@ -187,7 +187,7 @@ In the code above, the `h1` element is only rendered if the user object is truth
You can also use a direct `if` statement this way:
```js
```jsx
function Greeting({ isLoggedIn }) {
if (isLoggedIn) {
return <h1>Welcome back!</h1>;
@@ -221,7 +221,7 @@ function NameList({ names }) {
- Inline styles in React allow you to apply CSS styles directly to JSX elements using JavaScript objects.
- To apply inline styles in React, you can use the style attribute on JSX elements. The style attribute takes an object where the keys are CSS properties in camelCase and the values are the corresponding values. Here's an example:
```js
```jsx
function Greeting() {
return (
<h1
@@ -239,7 +239,6 @@ You can also extract the styles into a separate object and reference it in the `
```jsx
function Greeting() {
const styles = {
color: 'blue',
fontSize: '24px',
@@ -256,7 +255,6 @@ export default Greeting;
```jsx
function Greeting({ isImportant }) {
const styles = {
color: isImportant ? 'red' : 'black',
fontSize: isImportant ? '24px' : '16px'
@@ -161,7 +161,7 @@ import axios from "axios";
Then you can fetch the data using `axios.get`:
```js
```jsx
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
@@ -246,7 +246,7 @@ const [optimisticState, addOptimistic] = useOptimistic(actualState, updateFuncti
Here is an example of using the `useOptimistic` hook in a `TaskList` component:
```js
```jsx
"use client";
import { useOptimistic } from "react";
@@ -274,7 +274,7 @@ export default function TaskList({ tasks, addTask }) {
- **`startTransition`**: This is used to render part of the UI and mark a state update as a non-urgent transition. This allows the UI to be responsive during expensive updates. Here is the basic syntax:
```js
startTransition(action)
startTransition(action);
```
The `action` performs a state update or triggers some transition-related logic. This ensures that urgent UI updates (like typing or clicking) are not blocked.
@@ -297,13 +297,13 @@ const memoizedSortedArray = useMemo(
```js
const handleClick = useCallback(() => {
// code goes here
// code goes here
}, [dependency]);
```
- **`React.memo`**: This is used to memoize a component to prevent it from unnecessary re-renders when its prop has not changed.
```js
```jsx
const MemoizedComponent = React.memo(({ prop }) => {
return (
<>
@@ -414,13 +414,13 @@ In this example we have a dynamic segment called `category`. When a user navigat
- **`useParams` Hook**: This hook is used to access the dynamic parameters from a URL path.
```js
```jsx
import { useParams } from "react-router";
export default function Category() {
let params = useParams();
{/* Accessing the category param: params.category */}
{/* rest of code goes here */}
{/* Accessing the category param: params.category */}
{/* rest of code goes here */}
}
```
@@ -460,7 +460,7 @@ export default function Page() {
- **Context API**: Context refers to when a parent component makes information available to child components without needing to pass it explicitly through props. `createContext` is used to create a context object which represent the context that other components will read. The `Provider` is used to supply context values to the child components.
```js
```jsx
import { useState, createContext } from "react";
const CounterContext = createContext();
@@ -135,7 +135,7 @@ export default Profile;
- **Updating Arrays in State**: When updating arrays in state, it is important not to directly modify the array using methods like `push()` or `pop()`. Instead you should create a new array when updating state:
```jsx
```js
const addItem = () => {
const newItem = {
id: items.length + 1,
@@ -149,7 +149,7 @@ const addItem = () => {
If you want to remove items from an array, you should use the `filter()` method, which returns a new array after filtering out whatever you want to remove:
```jsx
```js
const removeItem = (id) => {
setItems((prevItems) => prevItems.filter((item) => item.id !== id));
};
@@ -210,7 +210,7 @@ Note that `dependencies` can be an array of "reactive values" (state, props, fun
Here is an example of creating a `useDebounce` hook:
```jsx
```js
function useDebounce(value, delay) {
const [debouncedValue, setDebouncedValue] = useState(value);
@@ -13,7 +13,7 @@ You learned in the previous lecture videos that JSX is a syntax extension for Ja
Here is a remainder of what JSX looks like:
```js
```jsx
const App = () => {
return (
<div>
@@ -11,7 +11,7 @@ Now that you have created the `isVisible` state variable, it is time to start us
In prior lecture videos, you learned about inline conditional rendering which allows you to show different content based on a certain condition. It is a common pattern to use the logical AND (`&&`) operator to conditionally render a piece of text like this:
```js
```jsx
function Notification({ message }) {
return (
<div>