어느날 갑자기 리액트를 하게 된 백엔드 개발자의 고군분투기...
회사 : 풀스택 해
React Hook이란?
리액트 훅(React Hooks)은 함수형 컴포넌트에서 상태(state)와 생명주기(lifecycle) 관련 기능을 사용할 수 있게 해주는 React의 기능이다.
리액트 훅이 등장하기 전에는 클래스형 컴포넌트만 상태 관리와 생명주기 기능을 사용할 수 있었으나, 훅 덕분에 함수형 컴포넌트에서도 이러한 기능을 쉽게 사용할 수 있게 되었다**useState**
- 상태를 함수형 컴포넌트에서 관리하기 위한 훅입니다.
- 초기 상태를 인자로 받고, 배열을 반환하며, 배열의 첫 번째 요소는 현재 상태 값, 두 번째 요소는 그 상태 값을 업데이트하는 함수
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
useEffect
- 컴포넌트가 렌더링될 때와 렌더링 후에 수행할 작업(사이드 이펙트)을 정의하는 훅이다. 예를 들어, API 호출, 구독, 타이머 설정 등을 처리할 수 있습니다.
- 기본적으로 useEffect는 컴포넌트가 마운트(처음 렌더링)될 때와 업데이트(리렌더링)될 때 실행됩니다.
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]); // 'count'가 변경될 때마다 실행됨
갑작스럽게 React 세상에 내던져진 나는 useState 원툴로 살아가고 있었다…
그러나 세상에는 더 많은 React Hook들이 있었다
useContext
- React의 Context API를 사용하여 컴포넌트 트리 전체에서 전역 상태를 쉽게 공유할 수 있도록 도와주는 훅
- useContext를 사용하면 하위 컴포넌트들이 props를 통해 상태를 전달받지 않고도 직접적으로 필요한 상태에 접근할 수 있다
const value = useContext(MyContext);
useReducer
- 복잡한 상태 로직을 관리할 때 사용된다
- Redux와 유사하게, 상태 업데이트 로직을 컴포넌트 외부에서 정의하는 구조를 제공한다
- useState가 관리하기에 너무 복잡한 상태일 경우 useReducer를 사용해 리듀서(reducer) 함수를 통해 상태를 관리한다
const [state, dispatch] = useReducer(reducer, initialState);
useRef
- DOM 요소나 어떤 값이 변경되어도 리렌더링되지 않고 유지되어야 하는 값을 저장하는 데 사용된다
- 보통 DOM 요소에 접근할 때 주로 사용되지만, 상태가 리렌더링에 영향을 미치지 않게 할 때도 활용된다
const inputRef = useRef(null);
function focusInput() {
inputRef.current.focus(); // input에 포커스 설정
}
useMemo
- 성능 최적화를 위해 계산된 값을 메모이제이션하는 훅
- 컴포넌트가 렌더링될 때마다 비용이 많이 드는 계산을 방지하기 위해 특정 값이 변경될 때만 재계산되도록 할 수 있다.
const memoizedValue = useMemo(() => expensiveCalculation(a, b), [a, b]);
useCallback
- 성능 최적화를 위해 함수의 메모이제이션을 제공하는 훅.
- 함수가 필요할 때마다 새로 생성되지 않고, 의존성 배열에 명시된 값이 변경될 때만 새로 생성된다.
const memoizedCallback = useCallback(() => {
doSomething(a, b);
}, [a, b]);
훅의 특징
- 함수형 컴포넌트에서만 사용 가능: 훅은 클래스형 컴포넌트가 아닌 함수형 컴포넌트에서만 사용할 수 있다
- 상태와 생명주기 기능 제공: 기존에 클래스형 컴포넌트에서만 사용되던 상태와 생명주기 기능을 함수형 컴포넌트에서도 사용 가능하다
- 커스텀 훅: 개발자는 여러 훅을 조합해 자신의 커스텀 훅을 만들어 재사용 가능한 로직을 손쉽게 구현할 수 있다
1번도 모른채로 리액트 하라고 던져진 나는 리액트 개발 첫날에 리액트 훅의 존재를 직접 겪으면서 알게 되었다…
전역으로 상태를 저장했다가 다른 파일에서 사용해야 할 일이 있었는데 이렇게 했다가 에러를 마주하게 된다
const handleOnSubmit = async () => {
const [dialog] = useDialogStore(state => [state.dialog]);
const [session] = useChatStore(state => [state.session]);
const dialogRequest = new DialogRequest({
test_case_id: dialog.name,
name: dialog.name,
description: dialog.description,
cid: session.cid,
author: dialog.author,
call_key: session.callKey,
result: dialog.result,
dialogv1: JSON.stringify(dialog.dialogv1),
dialogv2: ""
});
console.log(dialogRequest);
const result = await sendDialog(dialogRequest);
console.log(result);
dialog.clearDialogV1();
console.log("저장 버튼이 클릭되었습니다.");
}
지금보니 정말 이상하지만 2주 전의 나는 정말 아무것도 몰랐다…
🚨문제
src\\components\\atoms\\SimpleDialog.tsx
Line 46:22: React Hook "useDialogStore" is called in function "handleOnSubmit" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter. React Hook names must start with the word "use" react-hooks/rules-of-hooks
Line 47:23: React Hook "useChatStore" is called in function "handleOnSubmit" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter. React Hook names must start with the word "use" react-hooks/rules-of-hooks
🔎원인
React Hook을 React 함수 컴포넌트 또는 사용자 정의 Hook 외에서 호출했기 때문에 생기는 에러
React 컴포넌트로 옮겨주고 해결해줄 수 있었다
const SimpleDialog = ({title, children, onClose, open, maxWidth = false, showSave = true}: Props) => {
const [dialog] = useDialogStore(state => [state.dialog]);
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
handleClose(CloseType.SAVE);
}
'TIL(Develop) > React' 카테고리의 다른 글
[React] 페이지 로딩시에 단 한 번만 실행하기 (document.ready()같은 메서드) (1) | 2024.09.27 |
---|---|
[React] Destructuring assignment (2) | 2024.09.27 |