React hooks

Happhee·2022년 3월 21일
0

💙  React 💙

목록 보기
7/18
post-thumbnail
post-custom-banner

React에서 hook은 Class Component의 코드를 작성할 필요없이 state 관리와 Lifecycle을 Function Component에서도 사용할 수 있게 하기 위해서 등장한 기능이다.

어떻게 Class에서만 구현할 수 있었던 것을 hook으로 해결하였을까?

이에 대한 궁금증을 풀어보자.


✨ Hooks이란?

Class Component의 장점인 state, Lifecycle method를 Function Component로 가져오기 위한 것이다.

즉, Function Component에서 상태 관리를 할 수 있는 useState와 렌더링 직후의 작업을 설정하는 useEffect등의 기능을 제공하는 것을 말한다.

위의 기능들은 1차적인 렌더링 직후에 비동기 작업으로 처리되어야 할 부분을을 해결하기 위해 필요한 기능이다. 이러한 효과를 Side Effect라 한다.

예를 들어 서버로부터 데ㅔ이터를 가져오기 위해 API를 요청하면, 1차적인 렌더링 이후에 실제 데이터를 비동기로 가져와 리렌더링을 해주어야 한다.

Hook은 이 Side Effect를 수행하는 역할이라고 생각하면 된다.

바꿔야 하는 이유

super(props)의 불편함

Class Component에서 state를 사용하기 위해서는 super(props)를 사용해주어야 한다.
즉, React.Component에게 props를 넘겨주기 위한 것이다.
하지만, 똑같은 코드를 반복해서 작성하는 것은 상당히 불편하다.

this의 헷갈림

this를 어디에 bind해주느냐에 따라 props에 접근 할 수도, 불가능 할 수도 있다.

HOC 헬

React를 쓰다 보면, 자주 쓰는 코드를 따로 빼내어 작성해야 하는데, 여러 개가 겹칠 경우 HOC 헬이 발생된다.

예를 들어, 마우스의 위치를 가져오면서 window의 크기와 사용자의 정보를 한번에 가져오기 위한 HocHell을 살펴보자.👇

const HocHell = () => {
  return (
    <Hoc>
    	<WithMousePosition>
    		<WithWindowSize>
    			<WithUserLocation>
    				<SomeComponent />
    			</WithUserLocation>
    		</WithWindowSize>
    	</WithMousePosition>
    </Hoc>
  );
}

이를 Hook을 통해 간결화시킨 코드이다.👇

const Hook = () => {
  const mousePosition = useMousePosition();
  const windowSize = useWindowSize();
  const userLocation = useUserLocation();
  return (
    <SomeComponent 
    	mousePosition = { mousePosition }
		windowSize = { windowSize }
		userLocation = { useLocation }
  )
}

확연하게 코드의 가독성이 높아진 것을 확인할 수 있다.
또한, 보통 Hook은 use를 붙여 이름을 지어준다.


✨ 코드 작성 비교

숫자를 state로 가지고, 더하기 / 빼기 버튼을 클릭하여 값을 조정하는 예제를 통해 알아보자.

useState

  • Class Component
import React from 'react';
class App from React.Component{
  state = {
    number : 0
  };
  handleClickIncrement = () => {
    this.setState(state => ({
      number : state.number + 1
    }));
  };
  handleClickDecrement = () => {
    this.setState(state => ({
      number : state.number - 1
    }));
  };
  render(){
    return(
      <div style = {{"textAlign":"center"}}>
      	<div style={{"fontSize" : "50px"}}>{this.state.number}</div>
		<button onClick={this.handleClickIncrement}> + </button>
		<button onClick={this.handleClickDecrement}> - </button>
      </div>
    );
  }
}
export default App;
  • Function Component
import React , {useState} from 'react';
const App = () => {
  const [ number, setNumber ] = useState(0);
    return(
      <div style = {{"textAlign":"center"}}>
      	<div style={{"fontSize" : "50px"}}>{number}</div>
		<button onClick={()=> 
        	setNumber(number+1)}> + </button>
		<button onClick={()=>
			setNumber(number-1)}> - </button>
      </div>
    );
}
export default App;

useState를 통해서 Class Component의 state 선언과 관리를 간결하고 직관적인 코드로 변경시켜주었다.

useEffect

  • Class Component
import React from "react";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      number: 0
    };
  }

  componentDidMount() {
    document.title = `현재 ${number}`;
  }
  componentDidUpdate() {
    document.title = `현재 ${number}`;
  }
handleClickIncrement = () => {
    this.setState(state => ({
      number : state.number + 1
    }));
  };
  handleClickDecrement = () => {
    this.setState(state => ({
      number : state.number - 1
    }));
  };
  render(){
    return(
      <div style = {{"textAlign":"center"}}>
      	<p>현재 {this.state.number}</p>
		<button onClick={this.handleClickIncrement}> + </button>
		<button onClick={this.handleClickDecrement}> - </button>
      </div>
    );
  }
}
export default App;
  • Function Component
import React, { useState, useEffect } from 'react';
const App = () => {
  const [ number, setNumber ] = useState(0);
    // componentDidMount, componentDidUpdate와 같은 방식
  useEffect(() => {
    // 브라우저 API를 이용하여 문서 타이틀을 업데이트
    document.title = `현재 ${count}`;
  });

    return(
      <div style = {{"textAlign":"center"}}>
		<p>현재 {number}</p>
		<button onClick={()=> 
        	setNumber(number+1)}> + </button>
		<button onClick={()=>
			setNumber(number-1)}> - </button>
      </div>
    );
}
export default App;

useEffect를 사용하여 여러 줄의 차지하는componentDidMount와 componentDidUpdate를 대신하였다.


✨ 장점

  • 불필요한 코드를 사용하지 않기에 코드가 간결해지고 가독성이 좋아진다.
  • 많은 라이브러리들이 hook으로만 나오고 있다.
  • HOC 헬을 벗어 날 수 있다.
  • 공통 기능을 커스텀 hook로 만들어서 로직을 재사용하기 쉬워집니다.
  • 컴포넌트 자체에서 로직을 분리할 수 있어서 읽기 쉽고 테스트하기 쉬운 코드를 작성할 수 있습니다.

🌈 결론

useState, useEffect 외에도 useReducer등 React에 내장되어 있는 hook은 많다.
우리는 hook을 통해 코드의 재사용성의 이점을 끌어낼 수 있음을 확인하였고, 원하는 기능에 따라 Custom Hook을 사용할 수도 있다.
React를 개발할 때, 이점을 참고하여 개발하도록 하자.


📚 학습할 때, 참고한 자료 📚

profile
즐기면서 정확하게 나아가는 웹프론트엔드 개발자 https://happhee-dev.tistory.com/ 로 이전하였습니다
post-custom-banner

0개의 댓글