-
[유데미x스나이퍼팩토리] 프로젝트 캠프 : Next.js 2기 - 사전직무교육 2주차 - 리액트 hook프로젝트 캠프: Next.js 과정 2기 2024. 7. 25. 16:10728x90
학습 목표
리액트 훅의 종류를 익히고 각각의 사용 방법을 학습니다.
리액트 훅이란?
함수형 컴포넌트에서 사용할 수 있는 이미 만들어진 임의의 기능을 의미한다.
대표적으로 useState, useRef 등이 있다.useState
상태 변수를 선언하고 관리하는 데 사용하는 훅
지금까지 배운 내용으로 리액트에서 버튼을 눌러 숫자를 증가시키는 기능을 구현하고자 한다면 let으로 count 변수를 생성하고 버튼을 누를 때마다 count를 증가시키는 코드를 작성할 것이다. 그러나 이와 같이 코드를 작성하면 count의 값이 증가되더라도 그 결과가 화면에 표시되지 않게 된다.
그 이유는 리액트의 변수 추적 관찰과 관련이 있다. 대부분의 프레임워크는 변수의 변화를 감지하는 추적관찰 기능이 있다. 그러나 리액트의 경우 화면이 렌더링된 이후에는 더이상 변수를 추적 관찰하지 않는다.
따라서 버튼을 통해 count를 증가시켜도 리액트가 그 변화를 추적 관찰하지 않기 때문에 변화를 인지하고 화면에 반영해줄 수 없는 것이다.이때 필요한 기능이 바로 useState이다.
사용 방법
const [추적관찰할변수, 변경시킬변수] = useState(초기값);
useState 함수는 배열을 반환하며 우리는 이를 배열 비구조할당으로 받는다.
첫 번쨰 인자는 리액트가 추적 관리할 변수를 의미하고 두 번째 인자는 해당 데이터를 업데이트할 함수명을 의미한다.
따라서 관례상 두 번째 인자의 이름은 <set첫번째인자변수명> 을 사용한다.
예제 코드
import { useState } from "react"; const App = () => { const [count, setCount] = useState(0); return ( <> <h1>Count: {count}</h1> <button onClick={() => { setCount(count + 1); }} > 증가 </button> </> ); }; export default App;
만약 이때 한 번의 클릭으로 3씩 증가하는 기능을 만들고 싶다면 어떻게 코드를 작성해야 할까?
onClick={() => { setCount(count + 1); setCount(count + 1); setCount(count + 1); }}
만약 이렇게 코드를 작성한다면 의도와는 다르게 수정 전과 같이 1씩 증가하는 결과 를 얻게 된다.
왜 이렇게 되는 것일까?
이는 리액트의 batch update때문이다. 리액트는 퍼포먼스 향상을 위해 상태 업데이트를 합쳐서 이해한 다음 한번에 실행하기 때문에 위와 같은 코드를 작성하면 결과적으로 증가는 한 번만 실행되게 된다.
그렇다면 어떻게 작성해야 할까?
callback 함수를 사용하면 된다! (물론 setCount(count + 3);으로 작성해도 되지만 콜백 설명을 위해 넘어가자.)
callback
항상 상태의 최신 값을 사용한다.
사용방법
onClick={() => { setCount((prev) => prev + 1); setCount((a) => a + 1); setCount((count) => count + 1); }}
이렇게 작성하면 위에서 의도했던 대로 한 번의 클릭으로 3이 증가된 값을 얻을 수 있다.
이때 최신 상태 값의 이름을 마음대로 지정해줘도 되지만 보편적으로 prev 또는 currentValue를 많이 사용한다고 한다.
완전히 새로운 값을 지정한다면 setState를 사용하지만 만약 직전 상태의 영향을 받는 값으로 변경한다면 콜백을 사용하는 것이 좋다.
useRef
리액트에서 HTML 요소에 접근하거나 컴포넌트의 렌더링에 영향없이 값을 유지하고 싶을 때 사용한다.
일반적으로 값을 증감시키거나 특정 컴포넌트를 참조할 때 사용한다.
값 증감, 변동
useState와 동일하게 값을 추적하는 훅인데 값을 하나씩 증감시킬 때 사용함
다음과 같이 todo 객체의 id 값을 지정하기 위해 사용할 수 있다.
const App = () => { let uid = useRef(0); // 그냥 0을 할당하면 증가 없이 0만 사용됨 const [todos, setTodos] = useState<Todo[]>([]); const addTodo = () => { const todo = { id: uid.current++, // 항상 current라는 속성으로 접근하기 text: "아침먹기", }; setTodos((prev) => [...prev, todo]); }; return ( <div> <h1>할일 관리하기</h1> <pre>{JSON.stringify(todos)}</pre> <button onClick={addTodo}>할일추가</button> </div> ); };
이런 식으로 값을 증기시킬 수 있다. 이는 문자열에도 사용할 수 있다.
useRef에서 값에 접근할 때는 ref.current라는 속성을 통해 접근애햐 한다
참조
const App = () => { let inputEl = useRef<HTMLInputElement>(null); return ( <div> <input type="text" ref={inputEl} className="border border-slate-500" /> <button onClick={() => { console.log(inputEl.current?.focus()); }} > 출력 </button> </div> ); }; export default App;
동일한 useRef 객체를 여러 개의 컴포넌트에 ref로 할당할 수 있지만 결과적으론 가장 마지막에 등록한 컴포넌트에 참조로 등록된다. 즉, useRef는 한 번에 하나의 컴포넌트만 참조할 수 있다.
useId
react에서 고유한 id값을 보장해서 생성해주는 훅이다.
고유한 키를 생성해주면 반복 렌더링의 key로 사용해도 될까??
=> No! useId는 하나의 컴포넌트 안에서 하나의 id만 생성하기 때문에 만약 useId로 key를 부여하면 모든 아이템이 동일한 key를 갖게 될 것이다.그럼 item 컴포넌트 안에서 useId를 사용하는건 될까??
=> 이렇게 사용하면 모든 item 컴포넌트가 고유한 id값을 갖겠지만 그렇게 하면 key에 넣을 수 없어서 의미가 없다. 따라서 반복 렌더링에서 key에 useId를 사용할 수 없다!만약 객체 배열에서 객체에 key로 사용할 id값이 없다면 uuid를 사용하거나 Date.now()를 활용해서 id값을 지정하는 것이 좋을 것 같다.
728x90'프로젝트 캠프: Next.js 과정 2기' 카테고리의 다른 글
[유데미x스나이퍼팩토리] 프로젝트 캠프 : Next.js 2기 - 사전직무교육 2주차 - Context (0) 2024.07.26 [유데미x스나이퍼팩토리] 프로젝트 캠프 : Next.js 2기 - 사전직무교육 2주차 - useReducer (0) 2024.07.26 [유데미x스나이퍼팩토리] 프로젝트 캠프 : Next.js 2기 - 사전직무교육 2주차 - React 조건부 렌더링과 반복 렌더링 (0) 2024.07.25 [유데미x스나이퍼팩토리] 프로젝트 캠프 : Next.js 2기 - 사전직무교육 2주차 - React 데이터 전달 (0) 2024.07.24 [유데미x스나이퍼팩토리] 프로젝트 캠프 : Next.js 2기 - 사전직무교육 2주차 - React 시작하기 (1) 2024.07.23