리액트 훅

fe_sw·2022년 8월 1일
0

React

목록 보기
5/10
post-thumbnail

함수형 컴포넌트에서도 클래스형 컴포넌트의 라이프사이클 메서드처럼 다양한 기능을 지원하기위해 훅이 추가되었다. 리액트 v16.8 에 새로 도입되었다.

useState

상태를 관리한다. [state, setState] 순으로 반환 받아서 사용한다.
주의해야할점은 setState가 비동기적으로 실행된다.


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

useEffect

화면에 렌더링이 완료된 후에 수행되며, componentDidMount와 componentDidUpdate, componentWillUnmount 처럼 동작한다


useEffect(() => {}, []);

useEffect(() => {}, []);

useEffect(() => {
  return () => {
    console.log('컴포넌트가 화면에서 사라짐');
  };
}, []);

디펜던시 배열에 빈값 : 컴포넌트가 마운트될때 한 번만 호출 ->componentDidMount
디펀던시 배열에 값: 컴포넌트가 마운트될때 한 번 호출 + 해당값이 변경될때마다 호출 ->componentDidUpdate
안에 return문 : 컴포넌트가 언마운트될떄 호출 -> componentWillUnmount

useLayoutEffect

useLayoutEffect 는 비동기적으로 실행되는 useEffect와 달리 동기적으로 실행되고 내부의 코드가 모두 실행된 후 painting 작업을 거친다. 따라서 로직이 복잡할 경우 사용자가 레이아웃을 보는데까지 시간이 오래걸린다는 단점이 있어 웬만해서 쓰이지는 않는다.


  useLayoutEffect(() => {}, []);

useContext

Context는 부모 컴포넌트로부터 자식 컴포넌트로 전달되는 데이터의 흐름과는 상관없이 전역적인 데이터를 다룰 때 사용합니다. 전역 데이터를 Context에 저장한 후, 데이터가 필요한 컴포넌트에서 해당 데이터를 불러와 사용할 수 있습니다.

context API를 사용하기 위해서는 Provider , Consumer , createContext 이렇게 세가지 개념을 알고 있으면 된다.

  • createContext : context 객체를 생성한다.
  • Provider : 생성한 context를 하위 컴포넌트에게 전달하는 역할을 한다.
  • Consumer : context의 변화를 감시하는 컴포넌트이다.(함수형 컴포넌트에서는 useContext)

createContext

import { createContext, useState } from 'react';

const CountContext = createContext({
  count: 0,
  plusCount: () => {},
});

const CountProvider = ({ children }:): JSX.Element => {
  const [count, setCount] = useState(0);

  const plusCount = () => {
    setCount(count + 1);
  };

  return (
    <CountContext.Provider
      value={{
        count,
        plusCount,
      }}>
      {children}
    </CountContext.Provider>
  );
};

export { CountContext, CountProvider };

Provider


import { CountProvider } from './Contexts/Count';

import { CountLabel } from './Components/CountLabel';
import { PlusButton } from './Components/PlusButton';

function App() {
  return (
    <CountProvider>
      <CountLabel />
      <PlusButton />
    </CountProvider>
  );
}
export default App;

Consumer


import { useContext } from 'react';
import { CountContext } from '../../Contexts/Count';

export const CountLabel = () => {
  const { count } = useContext(CountContext);
  return <div>{count}</div>;
};

useReducer

useState의 대체 함수로 컴포넌트 상태 업데이트 로직을 컴포넌트에서 분리시킬 수 있다.
컴포넌트 바깥에 로직을 작성할 수 도 있고, 심지어 다른 파일에 작성한 후 불러와서 사용할 수도 있다.
reducer란 현재 상태와 액션 객체를 파라미터로 받아와서 새로운 상태를 반환해주는 함수 이다.

import React, { useReducer } from "react";

function reducer(state, action) {
  switch (action.type) {
    case "INCREMENT":
      return state + 1;
    case "DECREMENT":
      return state - 1;
    default:
      return state;
  }
}

function Counter() {
  const [number, dispatch] = useReducer(reducer, 0);

  const onIncrease = () => {
    dispatch({ type: "INCREMENT" });
  };
  const onDecrease = () => {
    dispatch({ type: "DECREMENT" });
  };

  return (
    <div>
      <h1>{number}</h1>
      <button onClick={onIncrease}>+1</button>
      <button onClick={onDecrease}>-1</button>
    </div>
  );
}

export default Counter;

useRef

특정 DOM 선택할때 주로 쓰이며 .current 프로퍼티 값으로 initialValue로 초기화되며, 변경 가능한 ref 객체를 반환한다. 반환된 객체는 컴포넌트의 전 생애주기를 통해 유지된다. useRef는 useState처럼 값을 변경해도 컴포넌트가 다시 랜더링되지 않는다. 따라서 값을 변경해도 화면에 반영이 되지않는다.document.querySelector 처럼 동작한다.

const refContainer = useRef(initialValue); //{current:initialValue}

특정DOM에 접근하고 싶을때 또는 상태값을 변경은 시키는데 컴포넌트를 리랜더링 시키지 않고싶을때 사용하면 된다.

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

function InputTest() {
  const counRef = useRef(0);

  const onChange = () => {
    countRef.current = counReft.current  + 1 
  };


  return (
    <div>
       <p>{countRef.current}</p> //항상 0
      <button onClick={onChange}>초기화</button> //버튼을 아무리 눌러도
    </div>
  );
}

export default InputTest;

useMemo

메모이제이션된 값을 반환합니다. 이미 연산 된 값을 리렌더링 시 다시 계산하지 않도록 한다. 의존성값이 변경되었을 때에만 다시 계산 한다다. 의존성 배열이 없는 경우 매 렌더링 때마다 새 값을 계산한다. 빈배열일 경우 처음계산한 값 쭉 간다.


const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

useCallback

메모이제이션 된 콜백을 반환한다. useMemo와 유사하게 useMemo는 값을 memoization한다면 useCallback은 함수를 memoization한다 의존성 값이 변경될때만 함수를 재생성하고, 그렇지 않다면 memoization한 함수를 재사용한다. useMemo와 다르게 의존성 배열 빈배열일 경우 처음 memoization한 함수를 매번사용한다.


const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);
useCallback(fn, deps)useMemo(() => fn, deps)와 같다.

memo

컴포넌트 리랜더링하는 조건은 크게 3가지다. props가 변경 되었을때, 부모 컴포넌트가 리랜더링 되었을때, state가 변경되었을때, 하지만 여기서 부모 컴포넌트가 리랜더링 되었을때 props가 변경되지 않았으면 자식 컴포넌트는 리랜더링 되지 않아도 되지만, 억울하게 랜더링이 일어난다. 부모컴포넌트가 리랜더링 되었을때 props가 변경되지않는한 리랜더링 시키지않는것이 react.memo이다

export function Movie({ title, releaseDate }) {
  return (
    <div>
      <div>Movie title: {title}</div>
      <div>Release date: {releaseDate}</div>
    </div>
  );
}

export const MemoizedMovie = React.memo(Movie);



참고

0개의 댓글