RE06 Exercises
Practical Exercises
- Using useCallback
Objective: Optimize a component with useCallback to prevent unnecessary re-renders.
Task:
Create a component List that renders items from a prop items. Include a button that toggles the sorting of the items. Use useCallback to ensure the sorting function does not cause unnecessary re-renders.
import React, { useState, useCallback } from 'react';
const List = ({ items }) => {
const [isSorted, setIsSorted] = useState(false);
const sortItems = useCallback(() => {
if (isSorted) {
return [...items].sort();
}
return items;
}, [items, isSorted]);
return (
<>
<button onClick={() => setIsSorted(!isSorted)}>Toggle Sort</button>
{sortItems().map((item, index) => <div key={index}>{item}</div>)}
</>
);
};- Using useMemo
Objective: Implement useMemo to optimize expensive calculations.
Task:
Create a component that calculates and displays the factorial of a number. Use useMemo to cache the factorial calculation.
import React, { useState, useMemo } from 'react';
const factorial = (n) => {
let result = 1;
for (let i = 2; i <= n; i++) {
result *= i;
}
return result;
};
const FactorialCalculator = () => {
const [number, setNumber] = useState(1);
const factorialOfNumber = useMemo(() => factorial(number), [number]);
return (
<div>
<input type="number" value={number} onChange={e => setNumber(Number(e.target.value))} />
<p>Factorial: {factorialOfNumber}</p>
</div>
);
};- Writing a Custom Hook
Objective: Write a custom hook to manage form inputs.
Task:
Create a custom hook useFormInput that manages the state of a form input. Use this hook in a component to create a controlled input.
import React, { useState } from 'react';
const useFormInput = (initialValue) => {
const [value, setValue] = useState(initialValue);
const handleChange = (e) => {
setValue(e.target.value);
};
return {
value,
onChange: handleChange
};
};
const FormComponent = () => {
const name = useFormInput('');
return (
<form>
<input type="text" {...name} />
<p>Your name is {name.value}</p>
</form>
);
};- Write a custom hook useOutsideClick that detects clicks outside of a given element and executes a callback function when such clicks occur.
Task:
Create a custom hook useOutsideClick that returns a ref and a callback function. The hook should add an event listener to the document that checks if the click target is outside the referenced element. If a click occurs outside the referenced element, the hook should call the provided callback function. Ensure the hook cleans up the event listener to prevent memory leaks.
import React, { useEffect, useRef } from 'react';
function useOutsideClick<E extends HTMLElement>(callback: () => void) {
const ref = useRef<E>(null);
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (ref.current && !ref.current.contains(event.target as Node)) {
callback();
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [callback]);
return ref;
};
const OutsideClickExample: React.FC = () => {
const handleOutsideClick = () => console.log("Clicked outside of the element");
const outsideClickRef = useOutsideClick<HTMLDivElement>(handleOutsideClick);
return (<div ref={outsideClickRef} style={{ border: "1px solid black", padding: "20px" }}>
Click outside of this box
</div>);
};
export default OutsideClickExample;