Hooks are great! I cannot say enough about them. If you are not in love with hooks yet, you will be. Hope it is not too presumptuous to say so.
Why do we love hooks and how are they different from regular components? When I had an ah-ha moment, it was not when I encountered all those existing hooks like useEffect, useState, useRef etc, but rather when I made my own custom hooks.
Hooks are stateful, so heavily rely on the closure mechanism. Each one of the hooks has a piece of memory attached to it, which can be retained. Here is a simple comparison between a stateful and stateless component.
function StatelessComponent({ data }) {
return <>{data}</>;
};
function StatefulComponent() {
const [data, setData] = React.useState()
return <>{data}</>;
}
A stateless component is just a pure function without any side-effects so what it returns always depends on the arguments that you pass in. In contrast, a hook is also a function but, it has stateful logic in it and it keeps the track of data.
Here is a simple custom hook for a pagination.
function usePagination({
initialPage,
prevPage,
nextPage,
latestPage,
oldestPage,
}: Props) {
const [current, setCurrent] = useState<number>
(initialPage);
//Storing the current page in the localStorage whenever it changes
useEffect(() => {
localStorage.setItem("page", current?.toString());
}, [current]);
//Removing the current page on clean-up.
useEffect(() => {
return () => {
localStorage.removeItem("page");
};
}, [latestPage]);
const latest = () => {
setCurrent(latestPage);
};
const previous = () => {
setCurrent(Math.max(0, current - prevPage));
};
const next = () => {
setCurrent(Math.min(latestPage, current + nextPage));
};
const oldest = () => {
setCurrent(oldestPage);
};
return {
current,
getLatest: () => latest(),
getPrev: () => previous(),
getNext: () => next(),
getOldest: () => oldest(),
};
}
export default usePagination;
Hooks makes your code DRY and keeps your data separate from one another and each defined hook caches data which you can persist and populate. You can just assign it and start using it right away.
function Pagination() {
const navigation = {
initial: 0,
prevSteps: 10,
nextSteps: 10,
latestPage: 273,
oldestPage: 273 % 10,
};
const pagination = usePagination(navigation);
useEffect(() => {
setPage(pagination?.current?.toString());
}, [navigation]);
return (
<div>
<Button onClick={pagination.getLatest}>
Latest
</Button>
<Button onClick={pagination.getPrev}>
Previous
</Button>
<Button onClick={pagination.getNext}>
Next
</Button>
<Button onClick{pagination.getOldest}>
Oldest
</Button>
</div>
);
}
This is it! You can make a component and give the navigation object as a prop and pass it into usePagination and so on. Well, you get the point! No longer need to worry about passing the state value to the parent component to keep track of the current page.
If you are like me, once you have the taste of hooks, you will be desperate to find places to replace hooks with.
Here is another useful custom hook to use for a toggle functionality.
function useToggle(initialState: boolean): [boolean, () => void] {
const [isOpen, setIsOpen] = useState(initialState);
const toggleSwitch = () => {
setIsOpen((prev) => !prev);
};
return [isOpen, toggleSwitch];
}
And you can call it like so.
const [toggle, setToggle] = useToggle(false);
To detect the size of a specific element? Easy.
function useWidthDetect(refWidth: React.RefObject<HTMLDivElement>) {
const [size, setSize] = useState<number | undefined>(0);
const handleSize = () => {
const { current } = refWidth;
const tableWidth = current?.offsetWidth;
setSize(tableWidth);
};
useLayoutEffect(() => {
handleSize();
window?.addEventListener("resize", handleSize);
return () => {
window?.removeEventListener("resize", handleSize);
};
}, []);
return size;
}
You don't always have to return somehting when you use hooks.
function useReset({
isSubmited,
setIsSubmited,
reset
}) {
React.useEffect(() => {
if (!isSubmited) return;
reset();
setIsSubmited(false);
}, [reset, isSubmited, setIsSubmited]);
}
Love hooks! They will save you from many headaches and prevent you from "Wrapper Hell" and having an evergrowing component. Do you like my article? What are the favorite hooks you made?
Top comments (5)
For people reading this make sure that the hook name must start with use otherwise react won't recognize it as a hook and won't allow you to use other hooks inside it
Thanks! yes it would be violating the rules of hooks.
Thanks for your knowledge sharing!
Thank you, Islom!
great to see you are focusing on every small thing . i really appreciate your work . How to perform istikhara for marriage