Lesson 3.6: Custom Hooks Implementation
In this guide, we'll learn how to create custom hooks that bridge the gap between our data layer and presentation layer, making it easy to access and manipulate data in our components.
Understanding Custom Hooks
Custom hooks are functions that encapsulate reusable logic and state management. They provide a clean interface for components to interact with our data layer.
Creating Post Management Hooks
Let's implement our post management hook that connects to our Redux store:
// modules/posts/hooks/index.ts
import { useAppDispatch, useAppSelector } from "@/store/useStore";
import { useEffect } from "react";
import {
createPost,
deletePostAction,
fetchPosts,
updatePostAction,
} from "../actions";
import { PostFormData, postSchema } from "../schemas";
export function usePosts() {
const dispatch = useAppDispatch();
const {
items: posts,
isLoading,
error,
} = useAppSelector((state) => state.post);
// Load posts
useEffect(() => {
dispatch(fetchPosts());
}, []);
const loadPosts = async () => {
dispatch(fetchPosts());
};
// Add post
const addPost = async (data: PostFormData) => {
const validated = postSchema.parse(data);
dispatch(createPost(validated));
};
// Update post
const updatePost = async (id: number, data: Partial<PostFormData>) => {
const validated = postSchema.partial().parse(data);
dispatch(updatePostAction({ id, data: validated as PostFormData }));
};
// Delete post
const deletePost = async (id: number) => {
dispatch(deletePostAction(id));
};
// Toggle complete
const toggleComplete = async (id: number) => {
const post = posts.find((p) => p.id === id);
if (post) {
dispatch(
updatePostAction({
id,
data: { ...post, completed: !post.completed },
})
);
}
};
return {
posts,
isLoading,
error,
refresh: loadPosts,
actions: {
loadPosts,
addPost,
updatePost,
deletePost,
toggleComplete,
},
};
}
Understanding the Hook Implementation
-
Store Connection
useAppDispatch
: Provides access to the Redux dispatch functionuseAppSelector
: Selects specific pieces of state from the store- Automatic loading of posts on component mount
-
Data Validation
- Uses Zod schema validation (
postSchema
) - Validates data before dispatching actions
- Type-safe data handling
- Uses Zod schema validation (
-
Action Methods
loadPosts
: Fetches all postsaddPost
: Creates a new post with validationupdatePost
: Updates existing post with partial datadeletePost
: Removes a post by ID
Best Practices
-
Hook Organization
- Keep hooks focused and single-purpose
- Group related functionality
- Use clear, descriptive names
-
State Management
- Use typed selectors for type safety
- Handle loading and error states
- Implement proper validation
-
Performance
- Use proper memoization
- Avoid unnecessary re-renders
- Implement proper cleanup
-
Error Handling
- Validate data before dispatching
- Handle API errors gracefully
- Provide meaningful error messages
Next Steps
Now that we have implemented our custom hooks, we can move on to implementing the UI components and connecting everything together.