# React/Hook

김하은·2022년 7월 24일
1

React

목록 보기
3/13
post-thumbnail

Hook 함수란?

함수 컴포넌트

장점

  1. 클래스형 커포넌트 보다 쉬운 선언
  2. 메모리 자원 덜 사용
  3. 최종 결과물 빌드 후 배포할때에 파일 크기가 작음.

단점

  • State 와 라이프사이클 API 사용 불가능

→ 이문제를 해결해 주기 위해 React v16.8 업뎃이후 태어난 Hook .


Hook 의 태어난 Story

  • React는 컴포넌트간에 재사용 가능한 로직을 붙이는 방법을 제공하지 않음.
  • React 개발자 도구에서 React 애플리케이션을 본다면,
  • providers, consumers, 고차 컴포넌트, render props 그리고 다른 추상화에 대한 레이어로 둘러싸인 “래퍼 지옥(wrapper hell)“을 볼 가능성이 높았음.

래퍼 지옥이란? ( 콜백 지옥이랑 비슷한 모습)

👉 처음 리액 리액트를 접했을 때

UI을 재사용 가능한 component들로 나누고 다른데서도 쓸 수 있도록 작성했지만,

로직이 UI 및 리액트 life cycle에 너무 밀접하게 결합되어 있었기 때문에 어려움을 겪음.

중복된 코드들이 늘어나기 시작함.

( 문제의 중복 되어 있는 코드)


👉 방법을 찾음!

  • HOC(Higher Order Component)

화면에서 재사용 가능한 로직만을 분리해서 컴포넌트 (component) 로 만들고,

재사용 불가능한 UI와 같은 다른 부분들은 parameter로 받아서 처리하는 방법.

💥 하지만 이 방법을 쓰니 코드의 모습들에서 문제가 보이기 시작함.


계속 다른 부분에 있는 파라미터(parameter) 로 받아와서 코드를 쓰고 감싸주다 보니..


‼‼위 코드의 모습을 보면 여러 로직이 componentWillUnmount, componentDidMount 등의 리액트 life cycle에 흩어지게 되고, 함수는 단일 책임 원칙을 벗어나게 되고, 코드는 복잡해지고, 테스트는 점차 어려워지게 된다.

🚩로직을 분리하면서도 wrapper hells을 피할 수 있고, 리액트 component life cycle에도 종속적이지 않게 코딩을 어떻게 할까?


🎉/ React v16.8 / Hook 함수의 도입🎉

Hook 의 3가지 종류

📌1. State Hook

바뀌기 전

  • class의 state와 setState로 상태를 관리했음

ex)

{/* Hook 함수가 도입되기 전의 모습*/}
class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: "이름"
    };
  }

  render() {
  	return <input value={name} onClick={(e) => this.setState({ name : e.target.value })} />;
  }
}

👉바뀐 후

이제는 단순히 기존 class의 render() 단계에 해당되는 로직에 집중하면 된다.
그리고 state가 필요한 경우 useState를 사용하여 hook 을 한다.

ex)

import { useState } from 'react';

function Example() {
  const [name, setName] = useState("이름");

  return <input value={name} onChange={(e) => setName(e.target.value)} />;
}

👉 useState는 인자로 초기값을 받고, 현재 상태(name)와 현재 상태를 업데이트할 수 있는 함수(setName)를 반환해준다. 훨씬 코드가 깔끔해짐.

📌2. Effect Hook

  • useEffect는 함수 컴포넌트 내에서 side effects를 수행할 수 있게 한다.
  • 데이터 가져오기, 구독(subscription) 설정하기, 수동으로 React 컴포넌트의 DOM을 수정하는 것까지 이 모든 것이 side effects

[ 2가지의 side effects ]

  1. 정리를 이용하지 않은 함수
  2. 정리를 이용하는 함수

1. 정리(Clean-up)를 이용하지 않는 Effects

  • React가 DOM을 업데이트한 뒤 추가로 코드를 실행해야 하는 경우가 있다.
    네트워크 리퀘스트, DOM 수동 조작, 로깅 등은 정리(clean-up)가 필요 없는 경우들

ex) 정리가 필요하지 않은것은 그 어떤것도 반환하지 않는다.

  useEffect(() => {
    document.title = `You clicked ${count} times`;
  });

2. 정리(Clean-up)를 이용하는 Effects

  • useEffect함수의 SideEffect함수가 실행되기 전에는 작동하지 않는다.
  • 모든 SideEffect함수가 실행되기 전 작동한다.

ex)

const [enteredEmail, setEnteredEmail] = useState(''); //이메일(아이디) 입력값 저장
  const [emailIsValid, setEmailIsValid] = useState();   //패스워드 입력값 저장
  const [formIsValid, setFormIsValid] = useState(false); //유효성 여부 저장

useEffect(()=>{
    const identifier = setTimeout(() => {
      console.log("Checking from validity!")
      setFormIsValid(
        enteredEmail.includes('@') && enteredPassword.trim().length > 6
      )
    }, 500) //5초가 지난 후에 수행

    return ()=>{
      console.log("CLEAN UP!")
      clearTimeout(identifier)
    } //클린업 함수
  }, [enteredEmail, enteredPassword])

  const emailChangeHandler = (event) => {
    setEnteredEmail(event.target.value);
  };

  const passwordChangeHandler = (event) => {
    setEnteredPassword(event.target.value);
  };

클린업 함수가 사용된 부분

()=>{
      console.log("CLEAN UP!")
      clearTimeout(identifier)
    } //클린업 함수
    1. 아이디/패스워드 입력 시, useEffect함수 수행.
    2. 클린업 함수 수행- clearTimeout() 함수를 통해 이전에 부른 setTimeout함수를 취소한다.
    3. 5초 뒤, 폼 유효성 여부 확인한다.

🤔알고 넘어가기 Clean-up함수란?

  • 리액트가 다음 차례의 effect 를 실행하기전,
    이전의 렌더링에서 파생된 efffect 를 정리할때 실행되는것
    React는 컴포넌트가 마운트 해제되는 때에 정리(clean-up)를 실행한다.
    하지만 위의 예시에서 보았듯이 effect는 한번이 아니라 렌더링이 실행되는 때마다 실행된다.
    클린업은 📍비동기가 끝나기 전에 언마운트 되서 메모리 리스크 나는걸 방지하기 위해 하는것.

[ 📍비동기는 논블록을 기반한 방식인거고 📌논블럭은 다른 브라우저가 실행될때,
대기할 필요 없이 다른 데이터들도 처리할수 있음 ]

📌 논블록이란?
논블록이란 비동기 개념에서 만들어진 상태로
브라우저가(크롬) 실행되는 시간이 10분(요청)이라고 가정했을시에
브라우저가(크롬) 이 오픈(결과) 되기전까지 다른 브라우저(사파리 등등)은 시간을
대기 하지 않고 제약없이 자유롭게 사용할수 있는 상황을 논블록 상태.

페이지 이동, 특정 버튼 누르면 컴포넌트가 사라짐
특정 페이지를 나가버리거나 안나오게 해버리거나
비동기는 진행중인데 이벤트가 사라져 버리니까
에러가 나와, 이럴때 쓰는게 클린업 ( 이런 문제를 해결하기 위한 기술 개념)


📌3. useContext (컴포넌트를 중첩하지 않고도 전역 값 쉽게 관리)

🤔 useContext의 'Context'란?

  1. context는 React 컴포넌트 트리 안에서 전역적(global)이라고 볼 수 있는 데이터를 공유할 수 있도록 고안된 방법.
  2. context의 주된 용도는 다양한 레벨에 네스팅된 많은 컴포넌트에게 데이터를 전달하는 것.
  3. context를 이용하면 단계마다 일일이 props를 넘겨주지 않고도 컴포넌트 트리 전체에 데이터를 제공할 수 있다.
  • 탄생 배경

React로 개발을 하다보면, 상위 컴포넌트로부터 하위 컴포넌트에게 데이터를 전달해야하거나,
컴포넌트 트리 내에서 데이터를 전역족으로 관리를 할 상황이 자주 일어난다고 한다.
이때 컴포넌트 트리 구조가 복잡하거나 거대한 경우에는, 단순히 데이터를 넘겨주기 위한 용도의 컴포넌트가 생성되기도 한다.

ex) X라는 데이터를 D 컴포넌트에서 사용한다고 가정하자.

A→B→C→D

X가 엄청난 환승을 거쳐야한다. 아주 힘든 여정이다.

장기적으로 봤을 때 컴포넌트 트리 구조가 굉장히 복잡해지기 때문에 컴포넌트를 관리하는 것이 어려워지게 된다.

💥이때 !! context를 이용하면, 일일이 props를 넘겨주지 않고도 컴포넌트 트리 전체에서 데이터를 사용할 수 있다.

Context를 이용하면 각 컴포넌트에게 데이터를 명시적으로 props로 넘겨주지 않아도 컴포넌트끼리 데이터를 공유할 수 있다.
Context는 Provider와 Consumer로 이뤄지는데, MVC 패턴이나 Observer 패턴과 비슷하게 Provider의 값이 변경되면 Consumer가 이를 감지하고 자동으로 하위 컴포넌트에 변경 사항을 반영해준다.
출처: https://velog.io/@gwak2837/React-Hooks%EC%9D%98-%EC%9D%B4%ED%95%B4

1.createContext : context 객체를 생성한다.
2.provider : 생성한 context를 하위 컴포넌트에게 전달하는 역할을 한다.
3.consumer : context의 변화를 감시하는 컴포넌트이다

컴포넌트 트리 전체에서 언제 어디서나 전역적(global)으로 데이터를 사용할 수 있게 해주는 것이 Context이다.

profile
꾸준함을 이기는것은 없다

0개의 댓글