Hook Hook Hook

Taehee Kim·2022년 6월 17일
1

React

목록 보기
4/7
post-thumbnail

JavaScript에 허덕이는 와중에 React 수업을 듣게 됐다. Component를 만들어서 관리하고 import와 export는 하는 방식들을 배우는 게 재밌었는데, 진짜를 만났다. 그건 바로 Hook이었다. Hook 친구들이 무엇이고 예제를 통해 각자 어떤 차이가 있는지 정리해보기로 헀다. 나를 눈물 흘리게 했던 Hook... 회고 팀 동료와 함께 토론하면서 Hook을 이해한 내용을 정리했다.

💻 What is React?

먼저 React가 무엇이고, 왜 사용하는지 알는 것이 Hook을 공부하기 전에 알아야 한다.

React는 자바스크립트의 라이브러리 중 하나로, 사용자 인터페이스(UI)를 구축하는 데 사용한다.

장점

1. 빠른 업데이트와 렌더링 속도
virtualDOM을 사용하기 때문에 상태변화가 일어나면 전체 DOM이 렌더링이 되는 것이 아니라 수정이 필요한 부분만 레더링이 되기 때문이다.
2. Components Based
3. Reusability (재사용성)
컴포넌트를 통해 필요한 경우 새롭게 만들지 않고 코드를 재사하용 할 수 있어 개발 비용과 시간을 절약할 수 있다.
4. facebook meta의 빵빵한 지원
라이브러리도 생애 주기를 갖고 있는데 일단 Meta의 지원이 있기에 현재 안정적인 주기에 자리 잡아 있는 라이브러리라고 생각하면 된다.
5. React-Native 사용 가능
React- Ntive는 앱 애플리케이션을 만들 수 있는데 안드로이드와 IoS를 동시에 개발이 가능하고 앱 개발 진입 장벽이 낮다. => good


장점은 이렇게나 많은 React도 단점은 있다. 방대한 학습량과 자바스크립트와 달리 버전이 업데이트되면 새롭게 달라지는 문법들과 높은 상태관리 복잡도가 그 예다. 하지만 이 단점을 커버할 만큼 리액트를 배울 수록 정말 익숙해지면 너무 편리하고 기능 별 등 필요에 따라 컴포넌트화를 통해 코드를 짤 수 있다는 점이 너무 좋은 것 같다. 정말 전세계에서 인기가 있는 이유가 있다.

🎣 What is Hook?

그럼 이제 진짜 주제인 Hook을 알아보자.

Hook은 Class 컴포넌트와 달리 setState()함수를 통해 직접 state를 사용할 수 없는 것을 가능하게 해주는 역할을 한다. 함수형 Component는 부모 컴포넌트로가 자식에게 props 값을 전달받을 수는 있지만, 직접 수정이 불가하다. 반면, state는 값을 자유롭게 받아와서 사용할 수 있다. 그래서 함수형 Component에서 props대신 state를 사용하기 위해선 Hook series들의 필요한 것이다.

이제 예제를 통해서 총 3가지 Hook을 공부할 것이다.

1. useState

state를 사용하는 hook

state 값이 바뀔 때마다 재렌더링할 수 있게 ⇒ 값 변화를 반영

const [변수명, set함수명] = useState(초기값)

ex) 일반 변수로 이루어진 함수

버튼 클릭 시 count 값은 올라가지만, 재렌더링이 되지 않아서 화면에는 반영이 안됨!!

⇒ 그래서 useState를 사용해서 재렌더링되어 Update를 시켜주는 것!

// 일반 변수로 만들어진 함수

fucntion Counter(props){
	let count = 0;

	return(
		<div>
				<p>{count}</p>
				<button onClick = {()=> count++}>클릭</button>
		</div>
	)
}

2. useEffect

  • side effect를 받아와 실행
  • 리액트 side effect ⇒ 서버를 받아 오는 등의 행동
  • 다른 컴포넌트에 영향을 미칠 수 있으며, 렌더링 중에는 작업이 완료될 수 없기 때문
  • 의존성 배열: 이펙트가 의존하는 배열, 배열 안의 값이 하나라도 변경되면 이펙트 함수 실행

렌더링 실행 조건

  1. 기본 형태
    useEffect(이펙트 실행 함수, [의존성 배열]);

    맨 처음 렌더링 (아묻따 실행)
    의존성 배열 값의 변화 감지될 때


  2. 만약, mount와 unmount 시에 단 한 번씩만 렌더링하고 싶다면

useEffect(이펙트함수,[])


  1. 처음 실행/ 컴포넌트가 업데이트 될 때마다 렌더링

useEffect(이펙트함수)


📎 예제 코드

useState를 사용하여 count와 countTwo로 만들었고, count는 useEffect함수와 연결되어 있다.
두 useState의 차이점을 알아보면 좋다

import React, { useState, useEffect, useRef } from 'react';

function Counter() {
    // useState는 비동기, 그리고 상태변화면 렌더링
  const [count, setCount] = useState(0)
  const [countTwo, setCountTwo] = useState(0)

  // 랜더링 됨
  const handleCountUp = (e) => {
    setCount(count + 1)
    console.log(count) // 비동기 -> useEffect로 추적하면 동기 가능
  }
    // 랜더링 됨
  const handleCountUpTwo = (e) => {
    setCountTwo(countTwo + 1)
    console.log(countTwo) // 비동기 -> useEffect로 추적하면 동기 가능
  }
  
  useEffect(() => {
    console.log('count가 감시되고 있습니다.')
    console.log(`감시된 변수 : ${count}`)
  }, [count]) // count가 변경되는 것을 감시
  return(
    <>
      <div>{count}</div>
      <button onClick={handleCountUp}>up!</button>
      <div>{countTwo}</div>
      <button onClick={handleCountUpTwo}>up!</button>
    </>
  )
}

function App() {
  return (
    <div>
      <Counter/>
    </div>
  );
}

export default App;

코드 설명

일단 해당 코드를 실행하면 useEffect가 바로 발생된다! 왜??? 위에서 설명을 잘 보고 와라. useEffect는 첫 화면이 렌더링 되는 순간 아묻따 실행된다. 그렇기에 버튼을 눌러서 이벤트 함수를 실행시키지 않았는데도 콘솔창에 다음과 같이 찍히게 된다.

1) count 첫번째 버튼을 누르면 setCount(count+1) 함수때문에 문서 상 숫자는 1이 올라갔고, useEffect 함수가 의존 배열 값인 count의 변화를 감지하여 다시 콘솔창에 정상적으로 감시되고 있다고 알려주고 있다.
그럼 여기서 왜 콘솔창에서는 0이 찍힌걸까? 우리는 분명 1이 올라갔는데??? 그건 바로 useState 값 자체가 비동기이기 때문에 한 번 누르면 0, 두 번 눌러야 1이 된다.


2) 다시 새로고침을 하고 순수 useState인 countTwo를 버튼으로 값을 변경해보았다. 값이 문서에는 1로 변했지만 역시 콘솔창에는 비동기로 찍혀나온다.




3. useRef

Reference를 사용하기 위한 Hook

  • 특정 컴포넌를 직접 선택하기 위한 용도! !
  • refObject.current :현재 참조하고 있는 Element
  • 렌더링되지 않음, 값이 누적됨. 값을 기억/ 내부 데이터 변경되어도 별도로 알리지 않음

⇒ 변화를 알기 위해서는 callback ref

사용법)

const refContainer = useRef(초깃값);

<div ref={myRef}></div>

  • Virtual돔 ⇒ render ⇒ HTML DOM
  • 가상돔에서 수정, 변화(state. props)가 일어나면 그 부분만 다시 render
  • useRef는 일반 변수 설정한 것과 같은데! 단 값을 누적해서 기억하고 렌더링을 하지 않는다.

그리고 나중에 렌더링 되면 누적했던 값을 뱉는다! 퉷! ! !

📎 예제 코드

import React, { useState, useEffect, useRef } from "react";

function Counter() {
  const [countTwo, setCountTwo] = useState(0);
  // ref와 일반 변수는 변해도 렌더링 X
  // ref는 일반 변수처럼 쓰지만 0으로 초기화가 되지 않음(휘발 방지, 상태누적)
  // 일반 변수는 렌더링 되면 0으로 초기화(함수 안에 있으니 휘발)
  let countThree = useRef(0);
  let countFour = 0;

  // 랜더링 됨
  const handleCountUpTwo = (e) => {
    setCountTwo(countTwo + 1);
    console.log(countTwo); // 비동기 -> useEffect로 추적하면 동기 가능
  };
  // 클릭하면 변수의 값은 증가하지만 랜더링은 되지 않음
  const handleCountUpThree = (e) => {
    countThree.current = countThree.current + 1;
    console.log(countThree.current);
  };


  return (
    <>
      <div>{countTwo}</div>
      <button onClick={handleCountUpTwo}>up!</button>
      <div>{countThree.current}</div>
      <button onClick={handleCountUpThree}>up!</button>
    </>
  );
}

function App() {
  return (
    <div>
      <Counter />
    </div>
  );
}

export default App;

코드 설명

위에서 봤던 useEffect와 연결되지 않은 useState함수와 useRef함수가 있다.
useRef를 눌러 3번 눌러보았다. 그러자 console창에는 값이 누적되어 올가지만 문서 상 숫자는 올라가지 않고 있다. 그 이유는 바로 useRef는 값을 기억하고 누적하지만 렌더링이 되기 전까지는 자신의 누적 값을 보여주지 않는다.

그리고 나는 저 누적된 3이라는 숫자를 문서에서도 보여주기 위해 useState 버튼을 실행시켜 렌더링했다. 그랬더니 useRef가 지금까지 누적했던 값을 모두 뱉어내었다.

📎 예제 코드

import React, { useState } from "react";

function Counter() {
  // useState는 비동기, 그리고 상태변화면 렌더링
  const [count, setCount] = useState(0);
 
  let countFour = 0;

  // 랜더링 됨
  const handleCountUp = (e) => {
    setCount(count + 1);
    console.log(count); // 비동기 -> useEffect로 추적하면 동기 가능
  };

  // 랜더링되 안되고 다른 state가 변해서 재렌더링 되어도 0으로 초기화
  const handleCountUpFour = (e) => {
    countFour = countFour + 1;
    console.log(countFour);
  };

  return (
    <>
      <div>{count}</div>
      <button onClick={handleCountUp}>up!</button>
      <div>{countFour}</div>
      <button onClick={handleCountUpFour}>up!</button>
    </>
  );
}

function App() {
  return (
    <div>
      <Counter />
    </div>
  );
}

export default App;

코드 설명

초기값을 받아서 함수가 실행되기 때문에 콘솔에 찍힌 값은 계속 올라가지만, 일반 변수는 useRef와 마찬가지로 Rendering이 되지 않기 때문에 버튼을 누를 때마다 값이 올라가는 것이 보인다.

하지만 useRef와 다른점은 useRef는 값을 누적하기 때문에 렌더링 됐을 때 누적된 값을 뱉지만,

일반 변수로 설정했을 경우 값을 누적하지 못하고 다시 처음부터 초기화가 되기 때문에 콘솔창도 다시 0으로 돌아간다.

0개의 댓글