🚀 들어가며
드디어 리액트 강의 주차가 되었다. 강의 첫 날에는 기초적인 것을 많이 배웠다. 리액트 기초와 useEffect, useRef 모두 어느정도 알고 있었던 내용이지만, 강의를 통해 다시 복기할 필요성을 느낀 내용만 정리해보았다.
✅ 컴포넌트 분리하기
create-react-app으로 생성한 프로젝트의 App.js 중 일부를 컴포넌트로 분리해봤다.
- line 2,3 : 사용할 컴포넌트를 import 키워드로 불러와야 된다.
- line 9 : 하위 컴포넌트에 props를 전달할 수 있다. 숫자는 {} 안에 넣어서 전달하고, 문자는 "" 안에 넣어서 전달한다.
▪︎ Logo 컴포넌트
- line 1 : img 태그 src 속성에 사용될 로고를 불러온다.
- line 2: 전달 받은 props의 타입을 지정해줄 수 있다. 이때, 'prop-types'로부터 import 해야 한다.
▪︎ Paragraph 컴포넌트
- line 1 : 전달 받은 props의 타입을 지정하기 위해 역시 'prop-types'로부터 import 해왔다.
- line 2 : props에는 children이라는 프로퍼티가 존재한다. children에는 태그 안의 내용이 담겨있다.
- line 8 : 태그 안의 내용이 담긴 children 프로퍼티도 타입 지정이 가능하다. 이 때 타입은 node이고, .isRequired는 해당 프로퍼티를 반드시 전달받아야함을 의미한다.
✅ 자식 컴포넌트에서 부모 컴포넌트로 값 전달하기
- Point : 부모 컴포넌트(App.js)와 자식 컴포넌트(Counter.js)의 상태를 따로 만들고, 자식 컴포넌트에서 이벤트 발생시 이벤트 핸들러를 통해 부모로 부터 전달 받은 props(부모의 상태를 변경시키는 핸들러)를 호출한다.
✅ useEffect hook 기본 활용법
- useEffect hook은 감시 대상에 변화가 있을 경우 실행되도록 할 수 있다.
- useEffect hook은 처음 컴포넌트가 로드될 때 실행되도록 할 수 있다.(즉, 컴포넌트의 라이프 사이클에 활용할 수 있다.)
- useEffect hook은 전역으로 발생하는 이벤트를 사용할 때 쓸 수 있다.
- 현재 코드는 스크롤 y축을 출력하는 이벤트
- 전역 이벤트는 반드시 해제 해줘야하는데 useEffect hook의 return 키워드로 해제해주면 된다. (useEffect hook의 return 키워드 이후의 코드는 컴포넌트가 제거될 때 실행된다.)
✅ useRef hook 기본 활용법
▪︎ DOM 요소에 직접 접근하기
useRef 훅을 사용해서 DOM 요소에 접근할 수 있다는 것과, 이 점을 활용해서 input 태그에 focus() 처리를 할 수 있다는 것은 알고 있었다. 여기서 새롭게 알게된 내용이 하나 있다. 바로 다른 컴포넌트로 ref props를 전달해줄 수 있다는 것이다.
- line 11 : useRef()를 통해 ref 객체를 초기화한다.
- line 14 : Input 컴포넌트의 props로 ref 객체를 전달한다.
- line 16 : 버튼을 클릭하면 inputRef.current(<input>)에 포커스가 된다.
- line 3 : React.forwardRef((props, ref) => { return jsx }); 함수를 활용한다. 이 때, 두 번째 파마리터로 다른 컴포넌트에서 생성한 ref 객체를 전달한다.
- line 6 : 다른 컴포넌트(App.js)에서 버튼 클릭시 포커스되는 함수에 의해 Input 컴포넌트의 input 태그가 포커스된다.
▪︎ 지역 변수로 사용하기
useRef hook을 지역 변수로 사용할 수 있다. 예를 들어, setInterval 함수의 타이머 id를 useRef hook을 사용하여 지역 변수에 할당할 수 있다.
- line 5 : 빈 ref 객체를 갖는 intervalId 지역 변수를 초기화한다.
- line 7 : Start 버튼 클릭 시 실행되는 이벤트 핸들러. 1초마다 count가 1씩 증가하는 setInterval 함수의 타이머 id를 ref 객체에 할당했다.
- line 13 : ref 객체에 할당된 타이머를 clear한다.
또 중요한 것은 useState와 useRef의 차이점은 값이 변경될 때 렌더링 여부이다.
- useState : 값이 변경되면 컴포넌트가 다시 렌더링된다.
- useRef : 값이 변경되더라도 컴포넌트가 다시 렌더링되지 않는다.
이것에 대해 정확하게 체감되지 않았는데 아래의 블로그 포스팅을 보고 이해할 수 있었다.
useRef의 새로운 발견 (useState와 비교)
컴포넌트는 자신의 상태값이 변경되거나, 부모로 부터 받은 인자값이 변경되었을 때 새로 렌더링된다. 심지어 useMemo나 useCallback, React.memo 등 최적화함수가 적소에 사용되지 않은 경우 부모로부
velog.io
아래의 코드는 이메일 입력 후 회원가입 버튼 클릭 시 입력한 이메일이 결과에 표시되는 코드이다.
import { useState, useCallback } from 'react';
export default function SignUp() {
const [mail, setMail] = useState('');
const [result, setResult] = useState('');
console.log('렌더가 된다.');
const onSubmit = useCallback((e) => {
e.preventDefault();
setResult(result);
// 최종적으로 onSubmit 이벤트(제출) 발생 시 useState 훅이 사용됨.
// -> 컴포넌트 리렌더링
}, []);
return (
<div id="container">
<form onSubmit={onSubmit}>
<label id="email-label">
<span>이메일 주소</span>
<div>
<input
type="email"
id="email"
name="email"
value={mail}
onChange={(e) => setMail(e.target.value)}
// input 태그에 onChange 이벤트가 발생하면 useState 훅이 사용됨
// -> 컴포넌트 리렌더링
/>
</div>
</label>
<span>결과: {result}</span>
<button type="submit">회원가입</button>
</form>
</div>
);
}
위 코드의 경우 useState만 사용했을 경우이다. input 태그의 onChange 이벤트 발생 시 상태값을 변경시키게 되고 불필요한 컴포넌트 리렌더링이 계속해서 발생하게 된다.
이를 해결하기 위해 useRef를 사용할 수 있다.
import { useState, useCallback, useRef } from 'react';
export default function SignUp() {
const mailRef = useRef(null);
const [mail, setMail] = useState('');
console.log('렌더가 된다.');
const onSubmit = useCallback((e) => {
e.preventDefault();
const { current } = mailRef; // ref 객체에 저장된 값을 사용한다.
if (!current) return;
setMail(current.value);
// 최종적으로 ref 객체에 저장된 current(input 태그의 value)를 한 번만 사용하면서 한 번만 리렌더링된다.
}, []);
return (
<div id="container">
<form onSubmit={onSubmit}>
<label id="email-label">
<span>이메일 주소</span>
<div>
<input type="email" id="email" name="email" ref={mailRef} />
{/* 객체의 값이 변경되어도 리렌더링 되지 않는다. */}
</div>
</label>
<span>결과: {mail}</span>
<button type="submit">회원가입</button>
</form>
</div>
);
}
input 태그의 값이 변경될 때 ref 객체의 값만 변경이 되므로 리렌더링이 되지 않고 있다가 최종 결과 onSubmit 이벤트 발생시 한 번만 리렌더링 된다.
🛸 마치며
이번 강의를 통해 리액트 기본기를 점검할 수 있었고, 특히 useEffect, useRef의 간단한 예시를 보면서 더 깊게 이해할 수 있는 계기가 되었다. 모던 리액트 Deep Dive 책으로 리액트 훅에 대해 더욱 공부하고 앞으로 잘 활용할 수 있도록 노력해야겠다.
'프로그래머스 데브코스' 카테고리의 다른 글
[MIL-3] 231123 ~ 231225 프론트엔드 데브코스 회고 (0) | 2023.12.25 |
---|---|
[React] Styled Component, useMemo, useCallback, Custom Hook (0) | 2023.12.05 |
[Vite, ESLint, Prettier] Vite와 ESLint, Prettier를 사용해야 하는 이유 (0) | 2023.12.01 |
[React] 자식 컴포넌트의 데이터를 부모 컴포넌트로 전달하기 (feat. Todo List App) / useState, useEffect, useRef (0) | 2023.11.25 |
[MIL-2] 231027 ~ 231122 프론트엔드 데브코스 회고 (3) | 2023.11.22 |