React의 함수형 컴포넌트( Reat Hooks)

이병수·2020년 8월 9일
0

React

목록 보기
6/6
post-thumbnail

1차 프로젝트를 정신없이 후다닥 끝내고 정신이 들려는 순간 바로 시작된 2차 프로젝트!!!
1차와 똑같다면 위코드 부트캠픅라 아니지... 이번 프로젝트는 1차 프로젝트에는 상상도 못한 정체가 기다리고 있었는데

그것은 바로 함수형 컴포넌트 React Hooks 와 Styled Components


이틀 쉬고 또 프로젝트를 시작하는 마음에 마음이 뒤숭숭한테 첫 날부터 낯선 이들과의 조우에 우리는 굉장힝 당황했지만...

당황하지 않고

오늘은 함수형 컴포넌트 React Hooks에 대해 알아보자


등장배경 ❓

리액트 컴포넌트는 클래스형 컴포넌트 (Class Component)와 함수형 컴포넌트(Functional Componen)
로 나뉜다. 기존의 개발방식은 일반적으로 함수형 컴포넌트를 사용하되 state이나 Life Cycle Method를 사용할 때만 클래스형 컴포넌트를 사용하는 방식이었다.

그 이유는 클래스형 컴포넌트가 함수형 컴포넌트에 비해 가지는 단점 때문이다!

클래스형 컴포넌트 vs 함수형 컴포넌트❓

클래스형 컴포넌트 단점

1.코드가 길고 복잡하다

  • constructor, this, binding 등 지켜야 할 규칙이 많아서 코드가 복잡하고 길어진다.
    클래스 자체가 Life Cycle method로 인해 기본적으로 뚱뚱하다

2.컴포넌트 사이에서 상태와 관련된 Logic을 재사용하기 어렵다

  • 클래스형 컴포넌트에서는 High-Order Components(HOC)로 컴포넌트 자체를 재사용 할 수는 있지만 부분적인 DOM 관련 처리나 API사용 및 state을 다루는 등의 logic에 있어서는 경우에 따라 같은 로직을 2개 이상의 Life Cycle method에 중복해서 넣어야하는 등 재사용에 제약이 따른다.

이에 반해 hooks를 활용한 함수형 컴포넌트에서는 원하는 기능을 함수로 만든 후(hook) 필요한 곳에 훅 집어 넣어주기만 하면 되기 때문에 로직의 재사용이 가능해진다.

3. 함수형 컴포넌트의 성능
함수형 컴포넌트의 성능에 관한 글

✅ Hooks ‼️

함수형컴포넌트에 비해 가지는 이런 단점에도 불구하고 그동안 클래스형 컴포넌트를 사용했던 이유는 state 관리Life Cycle method의 사용때문이었다. 복잡하고 뚱뚱하지만 클래스의 힘을 빌려야만 React가 원활하게 작동하기 때문이다.

하지만 Hooks의 등장으로 함수형 컴포넌트에서도 이러한 클래스형 컴포넌트의 작업을 할 수 있게 되었다
기존의 클래스형 컴포넌트가 가지고 있던 복잡성, 재사용성의 단점들까지 해결하면서 말이다

How to use? 💯

Hooks 사용규칙 ✔️

  • 최상위(at the top level)에서만 Hook을 호출해야 합니다. 반복문, 조건문, 중첩된 함수 내에서 Hook을 실행하지 마세요.
  • React 함수 컴포넌트 내에서만 Hook을 호출해야 합니다. 일반 JavaScript 함수에서는 Hook을 호출해서는 안 됩니다. (Hook을 호출할 수 있는 곳이 딱 한 군데 더 있습니다. 바로 직접 작성한 custom Hook 내입니다. 이것에 대해서는 나중에 알아보겠습니다.) Class 에서 작동하지 않는다.

React에는 4가지의 Built-in Hooks(useState, useEffect, useRef, useReducer) 등이 있고 이외에도 다양한 커스텀 훅이 존재하지만 일단 가장 기본적이고도 핵심적인 역할을 하고 있는 useStateuseEffect 두 가지 Hook을 학습해보자~!~! ~👌

✅ useState

const [state, setState] = useState(initialState);

상태 유지 값과 그 값을 갱신하는 함수를 반환한다. 최초로 렌더링을 하는 동안, 반환된 state(state)는 첫 번째 전달된 인자(initialState)의 값과 같다.

setState 함수는 state를 갱신할 때 사용한다. 새 state 값을 받아 컴포넌트 리렌더링을 큐에 등록한다.

setState(newState); // setState와 동일하게 비동기 업데이트

다음 리렌더링 시에 useState를 통해 반환받은 첫 번째 값은 항상 갱신된 최신 state가 된다.

예제

// 클래스형 컴포넌트
class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Click me
        </button>
      </div>
    );
  }
}

함수형 컴포넌트

import React, { useState } from 'react';

// 함수 컴포넌트
function Example() {
  // 새로운 state 변수를 선언하고, count라 부르겠습니다.
  const [count, setCount] = useState(0);
	const [isModalActive, setIsModalActive] = useState(false);
	
	// 안 좋은 예시
	const [state, setState] = useState({
		color: "red",
		isActive: true
	})

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
			<button onClick={() => setIsModalActive(!isModalActive)}>modal btn</button>
    </div>
  );
}

FAQ

Q) useState() 하나에서 모든 상태 값을 관리하면 안될까요?


function Box() {
  const [state, setState] = useState({ left: 0, top: 0, width: 100, height: 100 });
  // ...
}

A) However, we recommend to split state into multiple state variables based on which values tend to change together.

function Box() {
  const [position, setPosition] = useState({ left: 0, top: 0 });
  const [size, setSize] = useState({ width: 100, height: 100 });

  useEffect(() => {
    function handleWindowMouseMove(e) {
      setPosition({ left: e.pageX, top: e.pageY });
    }
    // ...

useState하나에 여러 상태를 관리하는 방법은?

회원가입 사이트 같이 인풋창이 많은 경우 모든 상태값을 State으로 관리하는 건 비효율적이다.

const [userInfo, setUserInfo] = useState({
    firstName: "",
    lastName: "",
    email: "",
    userName: "",
    password: "",
  });


  const handleInput = (name, e) => {
    setUserInfo({ ...userInfo, [name]: e.target.value });
  };

이렇게 useState의 파라미터로 객체를 전달한다

✅ useEffect

useEffect 는 리액트 컴포넌트가 렌더링 될 때마다 특정 작업을 수행하도록 설정할 수 있는 기능이다.

쉽게 말하면, 클래스형 컴포넌트의 componentDidMount + componentDidUpdate 를 합친 형태라고 이해하면 된다!

참고사이트

(1)참고사이트
(2)위코드 노션
(3)리액트 공식문서

0개의 댓글