[TIL] 23.05.01

Minkyu Shin·2023년 5월 1일
1

TIL

목록 보기
19/44
post-thumbnail

오늘의 나는 무엇을 배웠을까?

1. 제어 컴포넌트와 비제어 컴포넌트

React 공식 문서에 따르면, React에 의해 값이 제어되는 폼 엘리먼트를 "제어 컴포넌트" 그렇지 않은 엘리먼트를 "비제어 컴포넌트" 라고 부른다고 한다.
근데 사실 이게 무슨 의미인지 와닿지 않는다. 조금 더 쉬운 이해를 위해 아래에 각각 정리를 해보려 한다.

1-1. 제어 컴포넌트 (Controlled Component)

input 태그의 value 속성을 지정하고 사용한다.
이 때 value 의 값이 State 인지 Prop 인지는 중요하지 않다.

function App() {
  const [input, setInput] = useState("");
  
  const handleChange = (e) => {
    setInput(e.target.value);
  }
  
  return (
    <form>
      <input value={input} onChange={handleChange} />
    <form>
  );
}

위 코드는 input 의 값이 변경될 때마다 handleChange 함수를 통해 state 값을 업데이트 해 주는 제어 컴포넌트이다.
input 의 value는 항상 컴포넌트의 input state 와 일치하게 되고, 이에 따라 사용자가 입력한 값과 리액트에서 사용하는 값이 실시간으로 동기화된다. 따라서 제어 컴포넌트의 value는 항상 최신값을 유지한다.
또한, 제어 컴포넌트는 사용자가 입력을 할 때마다 리렌더링을 하게 된다.

제어 컴포넌트를 사용하는 경우

  • 유효성 검사
  • 실시간으로 필드 검사를 하는 경우
  • 조건에 따라 버튼의 활성화 여부가 바뀌는 경우

물론 항상 제어 컴포넌트를 사용해야 하는 것은 아니므로, 상황에 맞게 잘 사용해 보자.

제어 컴포넌트 사용의 문제점

앞서 제어 컴포넌트의 경우 입력이 발생할 때마다 state가 갱신되기 때문에 불필요한 리렌더링, 또는 API 요청을 하게 되고 자원 낭비 문제가 생길 수 있다.
이를 해결하기 위해서,

  • 스로틀링(throttling)
    마지막 함수 호출 후 일정 시간이 지날 때까지 다시 호출되지 않도록 하는 것
  • 디바운싱(debouncing)
    연이어 호출되는 함수들 중 마지막 또는 제일 처음만 호출하도록 하는 것

의 방법을 활용할 수 있다.

1-2. 비제어 컴포넌트 (Uncontrolled Component)

inputvalue 속성을 리액트에서 지정하지 않는 컴포넌트이다.

function App() {
  const [input, setInput] = useState("");
  
  const handleChange = (e) => {
    setInput(e.target.value);
  }
  
  return (
    <form>
      <input onChange={handleChange} />
    <form>
  );
}

제어 컴포넌트의 코드와 비교했을 때 input 태그의 value값을 따로 관리하지 않는 차이를 볼 수 있다. 이 때 리액트에서 사용하는 값과 실제 input 값에 차이가 생긴다.

제어 컴포넌트와는 다르게 비제어 컴포넌트는 사용자가 버튼을 클릭하는 행위와 같이 직접 트리거 하기 전까지 리렌더링을 발생시키지 않으며 사용자의 입력값과 리액트에서 사용하는 값을 동기화시키지 않는다.

비제어 컴포넌트를 사용하는 경우

  • 파일을 선택하는 input

1-3. 차이를 통한 사용법

  1. 실시간으로 값의 변화에 대한 피드백이 필요할 경우
    -> 제어 컴포넌트를 사용하자
  2. 실시간 피드백이 불필요하고 제출시에만 값이 필요하며, 불필요한 렌더링 또는 값 동기화를 피하고 싶을 경우
    -> 비제어 컴포넌트를 사용하자

2. Ref prop

HTML 엘리먼트에 대해 refprops 로 넘겨 주어 DOM 엘리먼트를 담거나, 콜백 함수를 넘겨 주어 DOM 엘리먼트를 매개변수로 접근할 수 있다.

Ref 객체의 생성

useRef 함수로 Ref 객체를 만들 수 있다.

import { useRef } from "react";

// ~~

const ref = useRef();

Ref 객체 사용하기

ref prop에 만들어진 Ref 객체를 내려준다

<input ref={ref} ~~ />

Ref 객체에서 DOM 노드 참조하기

Ref 객체의 current 프로퍼티를 사용하여 DOM 노드를 참조한다.

const node = ref.current;

DOM 노드의 경우 렌더링이 끝나야 생기기 때문에 ref 객체의 current 프로퍼티 값은 컴포넌트가 화면에 렌더링 되었을 때만 존재한다.
따라서, current 프로퍼티 값이 존재하는지 검사하고 사용해야 한다.

if (node) {
  //node 사용 코드
}

3. 사이드 이펙트 (Side Effect)

함수 내부에서 함수 밖의 값이나 상태를 변경하는 것

사이드 이펙트와 useEffect

리액트에서 useEffect 함수는 컴포넌트 함수 내에서 사이드 이펙트를 실행하고 싶을때 사용하는 것이다. 즉, 리액트 외부에 있는 데이터나 상태를 변경할 때 사용한다.
e.g. DOM 노드 직접 변경, 브라우저에 데이터 저장, 네트워크 리퀘스트

그렇다면 핸들러 함수를 사용할 수도 있고 useEffect 를 사용할 수 있는 경우에는 어떤 것을 선택해야 할까?
따로, 언제 써야 하는지 정해져 있지는 않지만 컴포넌트 안의 데이터와 리액트 밖의 데이터를 일치시키는 '동기화' 에 사용하면 유용하다.

정리 함수 (Cleanup Function)

useEffect 의 콜백에서 사이드 이펙트를 만들었을 때 정리가 필요한 경우가 있다. 이 때 콜백 함수에서 반환 값으로 정리하는 함수를 반환해 주면 사이드 이펙트에 대한 뒷정리가 가능하다.
정리 함수는 콜백 실행과 1:1로 대응되어 콜백 한 번 실행 시 반드시 한 번 실행된다. 새로운 콜백 함수가 호출되기 전 (앞에서 실행한 콜백의 사이드 이펙트 정리) 이나 컴포넌트가 화면에서 사라지기 전 (가장 마지막으로 실행된 콜백의 사이드 이펙트 정리) 에 실행된다.

내일의 나는 무엇을 해야할까?

  • React 데이터 다루기 마저 수강
  • React로 웹사이트 만들기 12강 까지 수강
  • 코드잇 / 팀 데일리 미션
profile
개발자를 지망하는 경영학도

0개의 댓글