Use Yup to validate email input
Yup.string().email("Invalid email address").required("Required")
<aside>
Yup needs to know the type of value (string) and then chain the different validation rules with their associated error message to show.
</aside>
What is the output?
You write “Wash the car” in the first ToDo input
You write “Buy bumper stickers” in the second ToDo input
You click the button to reverse the order
const ToDo = props => (
<tr>
<td>
<label>{props.id}</label>
</td>
<td>
<input />
</td>
<td>
<label>{props.createdAt}</label>
</td>
</tr>
);
function App() {
const [todos, setTodos] = useState([
{
id: 'todo1',
createdAt: '18:00',
},
{
id: 'todo2',
createdAt: '20:30',
}
]);
const reverseOrder = () => {
// Reverse is a mutative operation, need to create a new array first
setTodos([...todos].reverse());
};
return (
<div>
<button onClick={reverseOrder}>Reverse</button>
{todos.map((todo, index) => (
<ToDo key={index} id={todo.id} createdAt={todo.createdAt} />
))}
</div>
);
}
<aside>
Before clicking Reverse
After clicking Reverse
So the UI looks like this:
when reversing the order React understands they are still the same nodes with key=1 and key=2, so it will preserve their internal state (input value). Since the props are different though, it will just update the node with the new prop values.
key={index}.id, createdAt) but keeps the existing input DOM nodes, so the typed text does not move with the data.
</aside>Errors in ThemeProvider
import{ createContext, useContext, useState} from"react";
const ThemeContext = createContext(undefined);
// createContext deault value?
export const ThemeProvider= () => {
const[theme, setTheme] = useState("light");
return(
<ThemeContext.Provider
value={{
theme,
toggleTheme: () => setTheme(!theme),
//toggleTheme: () =>setTheme(theme === "light" ? "dark" : "light")
}}
>
</ThemeContext.Provider>
);
};
<aside>
[x] The toggleTheme implementation is incorrect.
it should be instead toggleTheme: () =>setTheme(theme === "light" ? "dark" : "light")
[x] the children are not passed through
ThemeProvider should use the children prop and pass it as a direct child of ThemeContext.Provider
</aside>
React Elements
<aside>
[x] The type of an element can be a DOM node, like a HTML button.
Correct, the type can be a DOM node.
[x] A tree of elements can mix and match both components and DOM elements as the type property.
Correct, they can be mixed and matched.
[ ] Each element object should have at least two properties: type and children
Not quite, please review the lesson item titled JSX, Components and Elements in lesson 1 of module 3.
[x] The type of an element can be a function corresponding to a React component, like a SubmitButton.
Correct, the type can be a React component.
</aside>
True or False: A tree of elements cannot mix and match both components and DOM elements as the type property.
<aside>
False → it is false to claim that they cannot be mixed and matched, actually, they can
</aside>
Submit Button
const Button = ({ children, ...rest }) => (
<button onClick={() => console.log("ButtonClick")} {...rest}>
{children}
</button>
);
const withClick = (Component) => {
const handleClick = () => {
console.log("WithClick");
};
return(props) => {
return<Component {...props} onClick={handleClick} />;
};
};
const MyButton = withClick(Button);
export default function App() {
return <MyButton onClick={() => console.log("AppClick")}>Submit</MyButton>;
}
True or false: When the user clicks the Submit button, the “WithClick” string will never be output to the console.
<aside>
True → "WithClick" will never be logged
Reason: although withClick defines handleClick that logs "WithClick", that function is only passed down as an onClick prop. The wrapped Button component does not use the passed onClick prop at all; it defines its own onClick handler
</aside>
what would be logged into the console when clicking the Submit button that gets rendered on the screen?
<aside>
What gets logged when clicking the Submit button:
due to the order of the spread operator in the different components, the withClick higher Order Component (HOC) takes precedence
ButtonClick
MyButton is created by withClick(Button)withClick overwrites the onClick prop with its own handleClickAppClick is discarded and never reaches ButtonInside Button:
<button onClick={() =>console.log("ButtonClick")} {...rest}>
onClick defined in Button runs{...rest} does not override it because it comes after onClick in JSX"WithClick" does not log because handleClick is passed as a prop but never used"AppClick" does not log because it is overridden by withClick
</aside>True or False: Using jest and react-testing-library, to assert that a function has been called with some specific arguments, you would need to use the toHaveBeenCalledWith matcher
<aside>
True → this is the proper matcher to check the arguments of the function call
</aside>
True or False: Using jest and react-testing-library, to assert that a function has been called with some specific arguments, you would need to use the toHaveAttribute matcher.
<aside>
False
</aside>
Valid examples of the render props pattern
<aside>
Render props means:
// no
<LoginUser renderUser={<p>Mark</p>} />
// yes - uses a render type prop that is a function that returns JSX
<MealProvider render={data => (
<p>Ingredients: {data.ingredients}</p>
)} />
// yes - uses a render type prop that is a function that returns JSX
// even though the name is not exactly “render”,
// explicit variations are also valid
<Row renderIcon={() => <Icon name="add">}/>
You need the below code snippet to run only after the initial render. What updates (if any) do you need to make to the code?
React.useEffect(()=> {
console.log('The value of the toggle variable is', toggle)
}, [])
<aside>
To run the effect only on the initial render, you need an empty dependency array.
</aside>
Re-render with useState
import {useState} from "react";
export default function App() {
const [restaurantName, setRestaurantName] = useState("Lemon");
function updateRestaurantName() {
setRestaurantName("Little Lemon");
};
return (
<div>
<h1>{restaurantName}</h1>
<button onClick={updateRestaurantName}>
Update restaurant name
</button>
</div>
);
};
<aside>
useState is the key reason neither restaurantName nor setRestaurantName is reset between re-renders.
restaurantName is not resetconst [restaurantName, setRestaurantName] = useState("Lemon");
"Lemon" is used only on the initial rendersetRestaurantName("Little Lemon") is called:"Little Lemon"), not "Lemon"So even though the component function runs again, restaurantName comes from React’s state store, not from re-executing useState("Lemon").
setRestaurantName is not resetsetRestaurantName is a stable function referenceReact does not recreate a new setter on each render; it reuses the same function tied to that state slot.
useState creates a persistent state slot that survives re-renders, which is why neither value is reset.
restaurantName persists because React stores state outside the componentsetRestaurantName persists because React provides a stable setterIs the following code snippet valid? Why?