참고
React Hook 2
useReducer
NOTE
useReducer는 컴포넌트에 리듀서를 추가할 수 있는 Hook이다!
import { useReducer } from 'react';
function reducer(state, action) { // reducer함수(type에 따라 동작시키는 함수)
if (action.type === 'incremented_age') {
return {
age: state.age + 1
};
}
throw Error('Unknown action.');
}
export default function Counter() { // 컴포넌트(버튼에 따라 값이 변경)
// [state, dispatch] = useReducer(reducer, initialState, init);
const [state, dispatch] = useReducer(reducer, { age: 42 });
// dispatch를 통해서 type을 변경한다.
return (
<>
<button onClick={() => {
dispatch({ type: 'incremented_age' })
}}>
Increment age
</button>
<p>Hello! You are {state.age}.</p>
</>
);
}
JavaScript
복사
•
state
◦
컴포넌트에서 사용할 상태
•
dispatch
◦
1번째 인자인 reducer 함수를 실행시킨다
◦
컴포넌트 내에서 state의 업데이트를 위해 사용된다.
•
rudecer
◦
컴포넌트 외부에서 state를 업데이트 하는 함수
◦
현재 state, action 객체를 인자로 받아, 기존의 state를 대체하여 새로운 state를 만들어 낸다
•
initialState
◦
초기 state
•
init
◦
초기 함수 (state를 조금 지연해서 생성하기 위해 사용)
useState와 useReducer
•
useState는 주요 state 관리도구이며, 개별 state나 독립적인 간단한 state관리에 적합하다.
•
useReducer는 복잡한 로직을 컴포넌트 함수 밖으로 이동시킬 수 있으며, 연관된 state 데이터 관리에 적합하다.
useMemo
useMemo는 비용이 많이 드는 계산 결과를 캐시할 수 있는 Hook이다!
import { useMemo } from 'react';
function TodoList({ todos, tab }) { // 재렌더링 간 계산 결과를 캐시한다.
const visibleTodos = useMemo(
() => filterTodos(todos, tab),
[todos, tab]
);
// ...
}
JavaScript
복사
React는 Virtual DOM을 통해서 변경된 부분만 효율적으로 업데이트를 해준다.
•
그런데 React는 Tree구조로 되어있고, 최상위 컴포넌트에서 아주 사소한 변화가 일어나더라도, 아래의 모든 컴포넌트들을 모두 재평가해야 하는가?
•
실제로 이러한 과정은 성능차이를 일으키며, 특정 상황에서 컴포넌트가 재실행하지 않는 방법을 도입했다!
•
비슷한 함수로 useCallback이 존재한다.
useRef
NOTE
useRef는 DOM 요소나 컴포넌트의 인스턴스에 접근하거나 값의 참조를 유지할 수 있습니다.
1. DOM 요소에 접근
function FocusInput() {
const inputRef = useRef(null);
const focusInput = () => {
inputRef.current.focus(); // input 요소에 포커스
};
return (
<div>
{/* ref를 통해서 참조값 설정 */}
<input ref={inputRef} type="text" />
<button onClick={focusInput}>포커스 주기</button>
</div>
);
}
export default FocusInput;
JavaScript
복사
Dom 요소 접근 1
interface NtcMttrUserDetailFormProps {
data: NtcMttrUserResponse;
}
const NtcMttrUserDetailForm = ({ data }: NtcMttrUserDetailFormProps) => {
// useRef의 타입을 HTMLTextAreaElement 또는 null로 지정
const textareaRef = useRef<HTMLTextAreaElement | null>(null);
useEffect(() => {
const textarea = textareaRef.current;
if (textarea) {
// 높이를 자동으로 초기화 & 실제 스크롤 높이로 높이 설정
textarea.style.height = 'auto';
textarea.style.height = `${textarea.scrollHeight + 40}px`;
}
}, [data.pstCn]); // data.pstCn이 변경될 때마다 높이 조절
return (
<Box mb="4" pointerEvents={'auto'} height={'100%'}>
<Box mb={'2'}>
<Text fontSize="xl" as="b">
공지사항 내용
</Text>
</Box>
<Flex gap="4" direction="column" height={'100%'}>
<DetailField label="제목" value={data.pstTtl}></DetailField>
<Textarea
ref={textareaRef}
value={data.pstCn}
isReadOnly
sx={{
minHeight: '500px',
}}
/>
</Flex>
</Box>
);
};
TypeScript
복사
Dom 요소 접근 2
2. 값의 참조 유지하기
useRef()를 사용하여 컴포넌트가 리렌더링되어도 값이 유지되도록 할 수 있습니다. 이 값은 컴포넌트가 리렌더링 되어도 변하지 않습니다.
function Counter() {
const [count, setCount] = useState(0);
const countRef = useRef(0);
const increment = () => {
setCount(count + 1);
countRef.current++; // count 값 보존
};
const showAlert = () => {
alert(`countRef 값: ${countRef.current}`);
};
return (
<div>
<p>State Count: {count}</p>
<p>Ref Count: {countRef.current}</p>
<button onClick={increment}>증가</button>
<button onClick={showAlert}>Alert Ref Count</button>
</div>
);
}
export default Counter;
TypeScript
복사