Ryu.log

[React] Hooks 본문

Front-end/React JS

[React] Hooks

류뚝딱 2019. 9. 26. 18:20

Hooks 사용법

Hooks는 React에서 Component를 함수형으로 개발 하도록하기위해 새로 만들어 졌다.

Hooks를 사용하면 함수형 컴포넌트를 사용하면서도 State제어가 가능하다.

또한 Class형 Component에 비해 획기적으로 코드량이 확연하게 줄어든다.

React에서는 기존 Class방식의 Component가 아닌 Hooks를 권장한다.

useState

hooks에서 state를 다룰때 사용된다.

import React, { useState } from 'react';

const App = () => {
  const [check, setCheck] = useState(0);
  const onClickEvent = () => setCheck(check + 1);
  return (
    <>
      <div onClick={onClickEvent}> Hooks! {check} </div>
    </>
  )
}

export default App;

위와 같이 구조분해 문법을 통해 변수를 선언하고. useState에 기본 값을 넣어준다.

배열의 첫번째 값 check는 현재 state를 의미한다.

배열의 두번째 값 setCheckstate가 변경될때 사용된다.

위 컴포넌트는 click할 때 마다 setCheck()를 불러와서 기존 check값에 1씩더하는 동작을 한다.

useRef

useRef는 hooks에서 ref에 접근하고 싶을때 사용된다.

즉, 기존에 document.querySelector('id')나 Class형 Component에서 사용되던 DOM 접근 방식이 아니라 useRef를 사용하여 DOM 노드에 접근한다.

import React, { useRef } from 'react';

const App = () => {
  const inputRef = useRef(null);
  const onClickEvent = () => inputRef.current.focus();
  return (
    <>
      <div>
        <input ref={inputRef} />
        <button onClick={onClickEvent}>input Focus</button>
      </div>
    </>
  )
}

export default App;

위와 같이 useRef를 불러온 뒤, 제어하고 싶은 Node의 ref속성에 넣어주고

하고싶은 event 처리를 진행하면 된다.

useRef를 사용할 때에는 타겟을 해당 refcurrent로 바라봐 주어야 한다.

// example
const onClickEvent = () => inputRef.current.focus();

useEffect

hooks에서 useEffect는 클래스형 component에서 사용되던 componentDidMount(), compnentDidUpdate(), componentWillUnmount() ... 등과같이
컴포넌트의 라이프 사이클을 이용하여 제어할때 이용된다.

보통 저런 라이프사이클 메소드를 사용하는 부분을,
hooks에서는 useEffect이용하여 처리한다고 보면 된다.

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

const App = () => {
  const [check, setCheck] = useState(0);
  const onClickEvent = () => setCheck(check + 1);

  useEffect(() => {
    console.log('componentDidMount, componentDidUpdate 역할(1:1 대응은 아님)'); // step 1
    return () => {
      console.log('componentWillMount 역할'); // step 2
    }
  }, [check]); // step 3

  return (
    <>
      <div onClick={onClickEvent}> Hooks! {check} </div>
    </>
  )
}

export default App;

useEffect를 사용하면 컴포넌트 업데이트의 감지가 가능해진다. 위 코드를 자세히 보면,

  • step1 부분이 componentDidMount, componentDidUpdate -> 두가지가 합쳐졌다 보면되며,
    컴포넌트가 첫 랜더링 되었을때나 컴포넌트가 리랜더링 되었을때를 감지할 수 있다.

  • step2 부분을 보면 함수를 리턴한다. 이부분은, componentWillMount의 역할을 하며, 컴포넌트가 제거되기 직전을 감지 할 수 있다.

  • step3 부분을 보면 배열에 값이 들어가 있다. 이 값은 useState를 통해 선언된 state값을 의미하며, 해당 state가 변경 되었을때 useEffect가 실행 된다.
    만약 값이 없는 빈배열이라면 componentDidMount 역할을 수행하며 컴포넌트가 첫 랜더링 되었을 때 실행된다.

정리 해보면, useEffectcomponent의 리랜더링 랜더링을 감지하여 동작할 수 있고,

이곳에서 비동기 요청 및 정리, 등의 처리를 할 수 있다.

state마다 다른 useEffect를 주고싶다면, useEffect를 여러번 중복해도 무관하다.

useLayoutEffect

useEffect와 비슷한 역할을한다. useEffect는 보통 화면이 랜더링 된 후 실행된다. 그러나, useLayoutEffect는 화면의 리사이징 즉, 레이아웃에 변화를 감지하는 Effect이다.

  • useEffect -> 화면이 완전히 바뀌고 난 후 발생
  • useLayoutEffect -> 화면이 바뀌기 전 발생

React.memo

React에서 컴포넌트는 state가 변경 되었을때 리랜더링된다.
React.memo를 사용한다면 관계없는 컴포넌트의 state가 변경되어도 전체가 리랜더링되는 낭비를 방지하여 성능개선을 할 수 있다.

이전 React class형 컴포넌트에서는 shouldComponentUpdate메소드를 사용하여 state,props의 변화를 감지 하였다.

더욱나아가 React.PureComponentclass형 컴포넌트에서 shouldComponentUpdate를 사용할 필요없이

자동으로 shouldComponentUpdate 기능을 지원해주는 컴포넌트를 만들어주어 편하게 성능 개선을 지원하였다.

Hooks에서 비슷한기능을 지원하는것이 바로 React.memo이다.

// App.jsx
import React, { useState } from 'react';
import Hello from './Hello';

const App = () => {
  const [hello, setHello] = useState(0);

  const onChangeEvent = e => {
    const makeArray = Array(e.target.value.length).fill({});
    setHello(makeArray.map((item, i) => (<Hello key={`${i + 1} 번`} num={i} />)));
  }
  return (
    <>
      <div>
        <input type="text" onChange={onChangeEvent} />
        {!hello ? '' : hello}
      </div>
    </>
  )
}

export default App;
// Hello.jsx
import React, { memo } from 'react';

const Hello = memo(({ num }) => {
  return (
    <div>Hello {num}</div>
  )
});

export default Hello;

위 코드의 실행결과는 input테그에 text를 입력하면 아래 input value length 만큼의 hello 텍스트가 출력된다.

ex) input.value가 test 라면 4개의 자식 hello컴포넌트가 생성됨

App.jsx파일에서 input value의 length만큼 즉, 4개의 child 컴포넌트 Hello.jsx를 불러오는데 여기서 기본적인 성능이슈가 생긴다.

App.jsxstate가 변경되기 때문에 그 child요소인 4개의 Hello컴포넌트 전부 리랜더링 되버리는 것이다.

이를 방지하기 위해 React.memo를 사용한다.

shouldComponentUpdateReact.PureComponent를 이용하여 불필요한 랜더링을 방지하던것과 마찬가지로

Hooks에서는 React.memo를 사용하여 불필요한 랜더링을 막는다.

React-dev-tools로 확인가능하나 현재 v4로 버전이 상승하여 highlight update기능이 사라져버림

기타

  • JSX 내에, classclassName으로 선언해야 한다.

  • JSX 내에, label테그의 forhtmlFor을 사용해야 한다.

'Front-end > React JS' 카테고리의 다른 글

[React] 성능최적화 (React.memo() 사용팁 정리)  (0) 2021.04.14
Comments