Custom Hooks Implementation
Scenario
In modern React development, abstracting reusable logic into custom Hooks is a fundamental practice for building maintainable and scalable applications. You’ve been tasked with developing two common custom Hooks: usePagination
for managing client-side pagination logic, and useDebounce
for debouncing rapidly changing values, often used with search inputs.
This lab will challenge you to think about hook design, state management within hooks, handling dependencies, and ensuring your hooks are generic enough for reuse.
Learning Objectives
Upon successful completion of this lab, you will be able to:
- Design and implement reusable custom React Hooks from scratch.
- Encapsulate complex logic and state management within a custom Hook.
- Effectively manage dependencies and side effects within custom Hooks.
- Understand how to return values and functions from custom Hooks for use in components.
- Apply custom Hooks to solve common problems like pagination and debouncing input.
- Consider basic performance aspects (e.g., memoization) where applicable within custom Hooks.
Project Requirements
You will create two custom Hooks in this lab. Each hook should be implemented in its own file (e.g., usePagination.ts
or usePagination.js
, useDebounce.ts
or useDebounce.js
).
You should also create an example components directory to demonstrate the usage of your custom hooks.
usePagination
Hook
Objective: Create a hook to manage pagination logic for a list of items.
Functionality:
- Inputs:
totalItems
: The total number of items to be paginated.itemsPerPage
: The number of items to display per page (default to 10).initialPage
: The page to start on (default to 1).
- Return Values (Object):
currentPage
: The current active page number.totalPages
: The total number of pages calculated based ontotalItems
anditemsPerPage
.startIndex
: The starting index of items for the current page (0-based).endIndex
: The ending index of items for the current page (0-based).itemsOnCurrentPage
: The actual number of items on the current page (useful for the last page).setPage(pageNumber)
: A function to jump to a specific page number.nextPage()
: A function to go to the next page.prevPage()
: A function to go to the previous page.canNextPage
: Boolean indicating if there is a next page.canPrevPage
: Boolean indicating if there is a previous page.
Implementation Details:
- Calculate
totalPages
correctly (e.g., usingMath.ceil
). - Ensure
currentPage
does not go below 1 or abovetotalPages
. startIndex
andendIndex
should be calculated based on thecurrentPage
anditemsPerPage
.itemsOnCurrentPage
should correctly reflect the count for the last page if it’s not full.
Example Usage Component (PaginationDemo.tsx
):
- Create a component that uses your
usePagination
hook. - Simulate a list of items (e.g., an array of 100 numbers or strings).
- Display the current page number, total pages, and the slice of items for the current page.
- Include buttons for “Previous”, “Next”, and jumping to specific page numbers (if you wish to demonstrate
setPage
more thoroughly). - Disable Previous/Next buttons when
canPrevPage
orcanNextPage
is false.
Example Solution
Pagination Demo
- Item 1
- Item 2
- Item 3
- Item 4
- Item 5
- Item 6
- Item 7
- Item 8
- Item 9
- Item 10
useDebounce
Hook
Objective: Create a hook to debounce a rapidly changing value.
Functionality:
- Inputs:
value
: The value to debounce (e.g., a search string from an input field).delay
: The debounce delay in milliseconds (default to 500ms).
- Return Value:
debouncedValue
: The value after the debounce delay has passed withoutvalue
changing.
Implementation Details:
- Use
useState
to store thedebouncedValue
. - Use
useEffect
to set up a timer (setTimeout
) whenever the inputvalue
ordelay
changes. - The effect should clear the timer (using
clearTimeout
) ifvalue
ordelay
changes before the timer fires (this is the core of debouncing). - When the timer finally fires, update the
debouncedValue
state.
Example Usage Component (DebounceSearchDemo.tsx
):
- Create a component with an input field.
- As the user types into the input, use the
useDebounce
hook to get the debounced version of the input’s value. - Display both the current input value and the debounced value.
- You can simulate an API call or filtering action whenever the
debouncedValue
changes by logging to the console (e.g., “Searching for: [debouncedValue]”).
Example Solution
Debounce Search Demo
Simulated Search Results:
Type to see results.
Implementation Guidelines
- Hook Design: Strive for clarity and reusability in your hook’s API.
- State Management: Use
useState
appropriately within your hooks. - Side Effects: Use
useEffect
for any side effects. Ensure correct dependency arrays and cleanup functions. - TypeScript (Optional but Recommended): If you are comfortable with TypeScript, try to type your hook inputs and return values for better self-documentation and safety.
Focus on the internal logic and API design of your custom Hooks. The visual styling of the demo components is secondary to the correct functionality of the hooks themselves.
Test your hooks thoroughly. Consider edge cases. For usePagination
, what happens if totalItems
is 0? For useDebounce
, how does it behave if the delay
changes?
Submission
Submit your project on Canvas via a GitHub link that includes all necessary files for this lab. Ensure your custom hooks and the demo components are included and functional.
Grading Rubric
Your submission will be evaluated based on the following criteria.
Criteria | Excellent | Good | Fair | Needs Improvement |
---|---|---|---|---|
usePagination Hook ImplementationCorrectly implements all specified functionality, manages state, and handles edge cases. | 15-13 pts • All return values correctly implemented and accurate. • Handles edge cases (e.g., 0 totalItems, invalid page numbers) gracefully. • Logic is clear, efficient, and well-organized. | 12-10 pts • Most return values correctly implemented. • Handles common cases well. • Minor issues in logic or edge case handling. | 9-7 pts • Basic pagination logic is present. • Several functionalities may be missing or incorrect. • Significant issues in logic. | 6-0 pts • Hook is largely non-functional or missing. • Core requirements not met. |
useDebounce Hook ImplementationCorrectly implements debouncing logic using useEffect with proper cleanup. | 15-13 pts • Debouncing works perfectly, updating only after delay. • useEffect has correct dependencies and cleanup (clearTimeout ).• Handles changes in value or delay robustly. | 12-10 pts • Debouncing generally works. • useEffect dependencies and cleanup are mostly correct.• Minor issues with rapid changes or delay updates. | 9-7 pts • Basic attempt at debouncing. • useEffect might be missing cleanup or have incorrect dependencies.• Debouncing is unreliable. | 6-0 pts • Hook is largely non-functional or missing. • Core debouncing logic is incorrect. |
Demo Component ShowcasePaginationDemo and DebounceSearchDemo effectively demonstrate the created hooks. | 10-9 pts • Both demo components clearly showcase all features of their respective hooks. • UI is functional and allows for easy testing of hook behavior. • Code is clean and easy to understand. | 8-7 pts • Both demo components showcase most features of the hooks. • UI is functional. • Minor clarity issues in demo code. | 6-5 pts • One or both demo components are incomplete or do not clearly showcase hook functionality. • UI may be difficult to use for testing. | 4-0 pts • Demo components are missing or non-functional. • Hooks are not demonstrated effectively. |
Total Points Possible: 40