리액트 Best Practice & Pattern 1탄

Sheryl Yun·2023년 8월 6일
0

리액트 Best Practice

목록 보기
2/4
post-thumbnail

fetch와 redux에서의 dispatch 커스텀 훅

  • API fetch 후 응답 값을 dispatch에 전달하는 과정 추상화
    • useSelector로 redux store에 있는 값을 가져올 수 있음
const useUser = () => {
	const dispatch = useDispatch();
    const state = useSelector(); // auth 정보 가져오기 등
    
    const fetchAllUsers = () => {
    	return fetch('/api/users')
        	.then((res) => res.json())
            .then((users) => dispatch({ type: "FETCH_USERS", payload: users }));
    };
    
    const fetchUser = (id) => {
    	return fetch(`/api/user/${id}`)
        	.then((res) => res.json())
            .then((user) => dispatch({ type: "FETCH_USER", payload: user }));
    };
    
    return { fetchAllUsers, fetchUser };
}
  • 컴포넌트에서 사용하기
    • 커스텀 훅이 반환하는 함수의 인자로 필요한 값 전달
const { fetchUser } = useUser();
const USER_ID = 1;

useEffect(() => {
	fetchUser(USER_ID);
}, []);

reducer에 switch문 대신 객체 + spread 조합

  • 객체 리터럴이 더 가독성이 높고 유지 보수하기 쉽다.
  • map 객체는 불필요한 재선언 방지를 위해 dispatch 문맥 바깥에 선언
const actionMap = {
	INCREMENT: (state, action) => ({ ...state, count: state.count + 1 }),
    DECREMENT: (state, action) => ({ ...state, count: state.count - 1 }),
};

const reducer = (state, action) => {
	const handler = actionMap[action.type];
    return handler ? handler : state;
};

REST 요청 커스텀 훅

  • react-query나 SWR를 쓰지 않을 경우 fetching을 위한 커스텀 훅
  • null을 여러 번 쓰는 배열에서 각각의 null 요소가 무엇을 나타내는지 알아보기 어려운 점
    • 추측해본 바 null이 들어있는 배열의 1번째 항은 error, 2번째 항은 응답으로 받은 data, 3번째 항은 loading 상태
  • useEffect의 auto가 무슨 뜻인지 모르겠다.. fetching을 할지 여부에 대한 플래그?
const useFetch = (input, { auto, ...init }) => {
	const [result, setResult] = useState([null, null, true]);
    
    const fetcher = useCallback(
    	(query, config) =>
        	fetch(query, config)
            	.then((res) => res.json())
                .then((data) => setResult([null, data, false]))
                .catch((err) => serResult([err, null, false])),
         [input, init]
    );
    
    useEffect(() => {
    	if (auto) fetcher(input, init);
    }, []); // 데이터 페칭을 단 한 번만 하고 싶은 경우 의존성 자리에 빈 배열 설정
    
    return [...result, fetcher]; // fetcher 함수 또는 POST 요청 함수
}
  • 컴포넌트에서 커스텀 훅 사용하기
const User = () => {
	const [err, users, loading, refetch] = useFetch('/api/users', { auto: true });
    
    const onClick = () => refetch(...);
    
    return (
    	<div>
        	{users.map((user) => <User key={user.id} user={user} />)}
        </div>
    );
}

code splitting 통한 동적 임포트 (React.lazy + Suspense)

  • React.lazy를 사용하면 필요할 때만 컴포넌트를 로드(동적 임포트)할 수 있다.
    • 예: Home 페이지에서는 Home 컴포넌트만 로드하고 About 페이지로 이동하면 그때 About 컴포넌트 로드
  • 추가로 Suspense로 Route들을 감싸고 fallback prop으로 컴포넌트를 로딩 중일 때의 UI를 넣어준다.
  • 간단해 보이는 방법이지만 컴포넌트가 100개 이상 많을 때 성능에 유의미한 차이
const Home = React.lazy(() => import('./Home'));
const About = React.lazy(() => import('./About'));

function MyComponent() {
	return (
    	<Suspense fallback={<div>Loading...</div>}>
        	<Route path="/home" component={Home} />
            <Route path="/about" component={About} />
        </Suspense>
	);
}

참고 자료

React best practices and patterns to reduce code - Part 1

profile
데이터 분석가 준비 중입니다 (티스토리에 기록: https://cherylog.tistory.com/)

0개의 댓글