React Hook 2

jinabbb·2022년 10월 25일
0

react hook

목록 보기
2/2

React Hook 정리하기 2

useReducer

복잡한 상태를 관리할때 사용하는 훅.Redux 라이브러리를 쓸 때 썼던 기억이 난다.

인자로 reducer와 initialState를 받고,

state와 dispatch를 리턴한다.

reducer는 previousState와 action(type과 payload를 가지는 객체)을 인자로 받고,

변경될 상태를 return하는 함수이다.

import React, { useReducer } from 'react';

const ACTIONS = {
	INCREMENT: 'increment',
	DECREMENT: 'decrement',
};

function reducer(state, action) {
	switch (action.type) {
		case ACTIONS.INCREMENT:
			return { count: state.count + 1 };
		case ACTIONS.DECREMENT:
			return { count: state.count - 1 };
		default:
			return state;
	}
}

const Reducer = () => {
	const [state, dispatch] = useReducer(reducer, { count: 0 });

	const increment = () => {
		dispatch({ type: ACTIONS.INCREMENT });
	};
	const decrement = () => {
		dispatch({ type: ACTIONS.DECREMENT });
	};
	return (
		<>
			<button onClick={decrement}>-</button>
			<span>{state.count}</span>
			<button onClick={increment}>+</button>
		</>
	);
};

export default Reducer;

하위컴포넌트에서 상위컴포넌트 상태를 변경해야할 때 dispatch만 넘겨주면 되니까 편할 것 같다.

useTransition

여기서부턴 사용해 본 적 없던 훅이다. 최근에 봤던 토스 slash 컨퍼런스에서 언급이 된걸 기억하니 함 봐보자.

모든 setState함수는 기본적으로 우선순위가 같다. 특정함수에서 setState함수를 여러번 호출한다면 모든 작업이 끝난뒤 상태가 변경된 다음 렌더링이 이루어진다. 만약 그 사이에 비동기처리등 시간이 오래 걸리는 작업이 있다면? ⇒ 그 모든 작업이 끝나서야 렌더링이 이루어진다.

이 순서를 바꾸기 위해 useTransition 훅을 사용한다.

리턴하는 isPending은 transition이 끝났는지 확인하는 값이고

startTransition에 우선순위가 낮은 함수를 넘겨준다.

import React, { useState, useTransition } from 'react';

const Transition = () => {
	const [isPending, startTransition] = useTransition();
	const [input, setInput] = useState('');
	const [list, setList] = useState([]);

	function handleChange(e) {
		setInput(e.target.value);
		startTransition(() => {
			const l = [];
			for (let i = 0; i < 20000; i++) {
				l.push(e.target.value);
			}
			setList(l);
		});
	}
	return (
		<>
			<input type='text' value={input} onChange={handleChange} />
			{isPending ? <div>loading...</div> : list.map((item) => <div>{item}</div>)}
		</>
	);
};

export default Transition;

useDeferredValue

위의 useTransition과 유사하게 낮은 우선순위를 지정하기 위한 훅이다. useTransition은 함수실행의 우선순위를 지정하고, useDeferredValue는 값의 우선순위를 지정한다.

우선순위가 높은 작업을 수행하면서 값의 업데이트를 지연시킨다.

import React, { useDeferredValue, useEffect, useMemo, useState } from 'react';

const List = ({ input }) => {
	const LIST_SIZE = 20000;
	const deferredInput = useDeferredValue(input);
	const list = useMemo(() => {
		const l = [];
		for (let i = 0; i < LIST_SIZE; i++) {
			l.push(<div key={i}>{deferredInput}</div>);
		}
		return l;
	}, [deferredInput]);
	useEffect(() => {
		console.log(`input : ${input}\n deferredValue:${deferredInput}`);
	}, [input, deferredInput]);
	return <div>{list}</div>;
};

const DeferredValue = () => {
	const [input, setInput] = useState('');

	function handleChange(e) {
		setInput(e.target.value);
	}

	return (
		<>
			<input type='text' value={input} onChange={handleChange} />
			<List input={input} />
		</>
	);
};

export default DeferredValue;

input이 계속 업데이트 되는 동안 defferedInput은 업데이트가 지연이 된다.

useLayoutEffect

useEffect와 비슷한데 useEffect는 DOM이 페인팅 된 이후에 동작하고 useLayoutEffect는 이전에 동작한다. 그리고 useEffect는 비동기적으로 동작하고 useLayoutEffect는 동기적으로 동작한다.

따라서 로직이 복잡할경우 useLayoutEffect를 사용하면 사용자가 컴포넌트를 보는데까지 오래걸린다. 화면이 깜빡이는 걸 보여주지 않는 단순한 작업을 할 때 사용하면 좋을듯 하다.

useDebugValue

customHook을 사용할 때 react-dev-tool에서 편하게 상태를 확인하기 위해 사용한다.

useId

유니크한 ID를 리턴해주는 훅

profile
개발

0개의 댓글