Một số custom hooks hay sử dụng cho React




Một số custom hooks hay sử dụng cho React






Hooks là một bổ sung mới trong React 16.8, nó là những function cho phép bạn
kết nối React state và lifecycle vào các components sử dụng hàm. React cung
cấp cho chúng ta những hooks có sẵn như useState, useEffect, useMemo, … và
đang tiếp tục bổ sung thêm các hooks hữu ích khác trong các phiên bản React
mới. Không chỉ có vậy, React cũng có phép chúng ta tự định nghĩa các custom
hooks để sử dụng. Trong bài viết này mình sẽ giới thiệu một vài custom hooks
hữu ích cho các bạn tham khảo nhé.



useWindowSize



Trường hợp chúng ta muốn lấy kích thước của trình duyệt (chiều rộng và chiều
cao), ta có thể sử dụng hook dưới đây; lưu ý là trường hợp code chạy phía
server (server-side) thì biến window sẽ trả về undefined.





function useWindowSize() {
// biến kiểm tra nó có phải client hay không
const isClient = typeof window === "object";

// lấy chiều rộng và chiều cao của cửa sổ của trình duyệt đang có
function getSize() {
return {
width: isClient ? window.innerWidth : undefined,
height: isClient ? window.innerHeight : undefined,
};
}

// state quản lý kích thước của trình duyệt
const [windowSize, setWindowSize] = useState(getSize);

// effect set kích thước của cửa sổ của trình duyệt
useEffect(() => {
if (!isClient) {
return false;
}

// set state kích thước của trình duyệt
function handleResize() {
setWindowSize(getSize());
}

// lắng nghe sự thay đổi kích thước của trình duyệt và set lại
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []); // chỉ chạy khi mount và unmount
return windowSize;
}





useQueryString hay usePushQueryString



React Router không hỗ trợ query string, nên nếu bạn muốn xử lý URL có chứa
params thì việc tạo 2 custom hook dưới đây là việc cần thiết. Trong 2 hooks
này mình sử dụng thêm thư viện query-string cho việc get hay set giá trị URL.





import { useMemo } from "react";
import { useLocation } from "react-router-dom";
import qs from "query-string";

function useQueryString() {
const location = useLocation();
const queryString = useMemo(
() => qs.parse(location.search),
[location.search]
);

return queryString; // { page: 1, search: 'deptrai', filter: 'male' }
}

export default useQueryString;







import { useHistory, useLocation } from 'react-router-dom';
import qs from 'query-string';

function usePushQueryString() {
const location = useLocation();
const history = useHistory();

function handlePushLocationSearch(data) {
const locationSearch = qs.parse(location.search);

history.push({ search: `?${qs.stringify({ ...locationSearch, ...data })}` });
}

return handlePushLocationSearch;
}

export default usePushQueryString;





useScrollToTop



Hook đơn giản nhất mình viết nhưng cũng được sử dụng rất nhiều, đấy là tính
năng cuộn lên đầu trang web. Cũng lưu ý các bạn là chỉ sử dụng khi ứng dụng
render ở client thôi nhé.





import React, { useLayoutEffect } from 'react'

function useScrollToTop() {
useLayoutEffect(() => {
window.scrollTo( 0,0)
}, [])
}

export default useScrollToTop





useCookie



Một hook mình viết khi sử dụng thư viện js-cookie cho việc quản lý cookie
trang web React của mình. Cookie giúp các bạn lưu trữ thông tin phiên đăng
nhập và xác thực website.





import { useState } from "react";
import * as Cookies from "js-cookie";

/**
* useCookie - React Hook for Cookies based on js-cookie
* @param {string} key Cookie
* @param {Object|string} [initialValue] Value will be assign if cookie doesn't exist.
* @returns {Array} Returns cookie value, and the function to update it.
*/
export function useCookie(key, initialValue) {
const [item, setInnerValue] = useState(() => {
return Cookies.get(key) || initialValue;
});

/**
* Set value of cookie
* @param {Object|string} value
* @param {Cookies.CookieAttributes} [options]
*/
const setValue = (value, options) => {
setInnerValue(value);
Cookies.set(key, value, options);
};

return [item, setValue];
}

export default useCookie;





usePrevious



Đây là hook giúp bạn lấy được giá trị trước đó của state và props trong React.
Trước đây nếu chúng ta sử dụng Class Component thì có thể sử dụng
componentDidUpdate, còn với Functional Component, chúng ta sử dụng useRef để
lưu lại giá trị props và state trước đó





function usePrevious(value) {
// Với ref, ta có thể lưu trữ bất kỳ giá trị nào, tương tự với việc thể hiện 1 instance của 1 lớp
const ref = useRef();

// lưu giữ giá trị hiện tại vào trong ref
useEffect(() => {
ref.current = value;
}, [value]); // Chỉ re-render khi giá trị thay đổi

// trả về giá trị trước đó
return ref.current;
}





useFetch



Mỗi khi cần call API get dữ liệu từ server mà không cần đẩy vào Redux hoặc 1
state management nào khác thì mình thường sử dụng hook này cho nhanh và tiện.





import { useState, useEffect } from "react";

export default function useFetch(url, options) {
const [data, setData] = useState([]);
const [error, setError] = useState(null);

useEffect(() => {
const fetchData = async () => {
try {
const resp = await fetch(url, options);
const res = await resp.json();
if (isMounted) setData(res.data);
} catch (e) {
if (isMounted) setData([]);
if (isMounted) setError(e);
}
};

let isMounted = true;
fetchData();
return () => {
isMounted = false;
};
}, []);

return { data, error };
}




useDebounce






import { useState, useEffect } from 'react';

function useDebounce(value, delay) {
const [deBounceValue, setDebounceValue] = useState(value);

useEffect(() => {
const handler = setTimeout(() => {
setDebounceValue(value);
}, delay);
return () => {
clearTimeout(handler);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [value]);

return deBounceValue;
}

export default useDebounce;





Kết bài



Trong quá trình làm dự án thì có rất nhiều tính năng mà bạn có thể viết lại
thành 1 custom hook. Trên đây chỉ là vài custom hook cơ bản mà hầu như dự án
React nào mình cũng sử dụng. Hy vọng bài viết hữu ích dành cho các bạn, cảm ơn
các bạn đã đọc và theo dõi. Hẹn gặp lại các bạn trong các bài viết tiếp theo
của mình.

Hiju Blog

I'm HiJu

Post a Comment

Previous Post Next Post