useTitle로 페이지 타이틀 최적화
각 페이지의 타이틀을 짓기 위해서 고민해서 다음과 같이 useTitle 훅을 만들어 해결했다.
import { useEffect } from 'react';
const useTitle = (title) => {
useEffect(() => {
const prevTitle = document.title;
document.title = title;
return () => (document.title = prevTitle);
}, [title]);
};
export default useTitle;ObserverIntersection Api 통해서 피드 무한스크롤 구현
useDebounce 사용해서 검색 최적화하기
한 글자만 쳐도 검색되는 문제 발견. 필요없는 요청이 많아진다.
// hooks/useDebounce.js
import { useEffect, useState } from 'react';
const useDebounce = (value, delay) => {
const [debouncedValue, setDebounceValue] = useState(value);
useEffect(() => {
const timer = setTimeout(() => setDebounceValue(value), delay || 500);
return () => {
clearTimeout(timer);
};
}, [value, delay]);
return debouncedValue;
};
export default useDebounce;const Search = () => {
const [keyword, setKeyword] = useState('');
const debouncedValue = useDebounce(keyword);
const [searchList, setSearchList] = useState([]);
useEffect(() => {
if (!keyword.length) return;
const searchUsers = async () => {
const { data } = await axiosPrivate.get(
`/user/searchuser/?keyword=${keyword}`,
);
setSearchList(data);
};
searchUsers();
}, [debouncedValue]);
return (
<>
<SearchHeader setKeyword={setKeyword} />
<S.Content>
<SearchList searchList={searchList} />
</S.Content>
</>
);
};- 불필요한 리렌더링을 막을 수 있다.
memo 사용해서 피드 무한스크롤 시 이전 게시글 최적화 작업
토큰 검증을 통한 사용자 인증 확인
const RequireAuth = () => {
const token = JSON.parse(localStorage.getItem('token'));
const location = useLocation();
return (
<>
{token ? (
<Outlet />
) : (
<Navigate to='login' state={{ from: location }} replace />
)}
</>
);
};
export default RequireAuth;const RequireAuth = () => {
const token = JSON.parse(localStorage.getItem('token'));
const location = useLocation();
const navigate = useNavigate();
useEffect(() => {
const isValid = async () => {
try {
const { data: isValid } = await axiosPrivate.get('/user/checktoken');
if (!isValid) {
localStorage.removeItem('token');
navigate('/login');
}
} catch (err) {
localStorage.removeItem('token');
navigate('/login');
}
};
isValid();
}, []);
return (
<>
{token ? (
<Outlet />
) : (
<Navigate to='login' state={{ from: location }} replace />
)}
</>
);
};
export default RequireAuth;