React Hook

Yooncastle·2021년 6월 28일
0

useState

리액트 16.8 이전 버전에서는 함수형 컴포넌트에서는 상태를 관리할 수 없었음
16.8부터 Hooks라는 기능이 도입되면서 함수형 컴포넌트에서도 상태 관리 가능

컴포넌트에서 동적인 값= State
useState함수를 사용하여 컴포넌트에서 상태를 관리할 수 있음

const [number, setNumber] = useState(0);

함수형 업데이트

기존 값을 어떻게 업데이트 할 지에 대한 함수를 등록하는 방식으로도 값을 업데이트 할 수 있음

  const onIncrease = () => {
    setNumber(prevNumber => prevNumber + 1);
  }

useRef

React에서 특정 DOM을 선택해야하는 상황에 ref 사용
함수형 컴포넌트에서 ref를 사용 할 때에는 useRef라는 Hook함수를 사용

const nameInput = useRef();
const onReset = () => {
	setInputs({
      name: '',
      nickname: ''
    });
    nameInput.current.focus();
  };
  return (
    <div>
      <input
        name="name"
        placeholder="이름"
        onChange={onChange}
        value={name}
        ref={nameInput}
      />
  

useRef로 컴포넌트 안의 변수 만들기

useRef는 DOM을 선택하는 용도 외에도 컴포넌트 안에서 조회 및 수정할 수 있는 변수를 관리하는 것

useRef로 관리하는 변수는 값이 바뀐다고 해서 컴포넌트가 리렌더링되지
않음

리액트 컴포넌트에서의 상태는 상태를 바꾸는 함수를 호출하고 나서 그 다음 렌더링 이후로 업데이트 된 상태를 조회할 수 있는 반면, useRef로 관리하고 있는 변수는 설정 후 바로 조회할 수 있음

  const nextId = useRef(4);
  const onCreate = () => {
    const user = {
      id: nextId.current,
      username,
      email
    };
    setUsers(users.concat(user));

    setInputs({
      username: '',
      email: ''
    });
    nextId.current += 1;
  };

useEffect

useEffect라는 Hook을 사용하여 컴포넌트가

  • mount 됐을 때
  • unmount 됐을 때
  • update 될 때

특정 작업을 처리하는 방법

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

첫번째 파라미터에는 함수,
두번째 파라미터에는 의존값이 들어있는 배열 deps를 넣음
deps 배열을 비우게 되면 컴포넌트가 처음 나타날때에만 useEffect에 등록한 함수가 호출됨

cleanup 함수

useEffect 에서는 함수를 반환 할 수 있는데 이를 cleanup 함수라고 부름
cleanup 함수는 useEffect 에 대한 뒷정리
deps 가 비어있는 경우에는 컴포넌트가 사라질 때 cleanup 함수가 호출

deps에 특정 값 넣기

deps에 특정값을 넣게 되면, 컴포넌트가 처음 mount/unmount 될 때에도 호출되고
지정한 값이 바뀔 때/바뀌기 직전에도 호출됨

  useEffect(() => {
    console.log('user 값이 설정됨');
    console.log(user);
    return () => {
      console.log('user 가 바뀌기 전..');
      console.log(user);
    };
  }, [user]);

useEffect 안에서 사용하는 상태나, props 가 있다면, useEffect 의 deps 에 넣어주어야 합니다. 그렇게 하는게, 규칙

만약 useEffect 안에서 사용하는 상태나 props 를 deps 에 넣지 않게 된다면 useEffect 에 등록한 함수가 실행 될 때 최신 props 상태를 가르키지 않게 됨

deps 파라미터 생략

컴포넌트가 리렌더링 될 때마다 호출됨

참고로 리액트 컴포넌트는 기본적으로 부모컴포넌트가 리렌더링되면 자식 컴포넌트 또한 리렌더링 됨(바뀐 내용 없어도)


useMemo

성능 최적화를 위해 연산된 값을 useMemo라는 Hook을 사용하여 재사용

const count = useMemo(() => countActiveUsers(users), [users]);

useMemo를 사용하지 않으면 컴포넌트가 랜더링될 때(input 태그에 입력이 발생할 때)마다 countActiveUsers가 호출됨

return (
    <>
      <CreateUser
        username={username}
        email={email}
        onChange={onChange}
        onCreate={onCreate}
      />
      <UserList users={users} onToggle={onToggle} onRemove={onRemove} />
      <div>활성사용자 수 : {count}</div>
    </>
  );

따라서 users에 변경이 생길 때에만 countActiveUsers가 호출 되도록 최적화하기 위해 useMemo 사용

첫번째 파라미터에는 어떻게 연산할지 정의하는 함수
두번째 파라미터에는 deps 배열

deps배열 안에 넣은 내용이 바뀌면 함수 호출해서 값을 연산
내용이 바뀌지 않았다면 이전에 연산한 값을 재사용


useCallback

useCallback 은 useMemo 와 비슷한 Hook

useMemo는 특정 결과값(count)을 재사용 할 때 사용하는 반면,
useCallback은 특정 함수를 새로 만들지 않고 재사용하고 싶을때 사용

한번 만든 함수를 필요할때만 새로 만들고 재사용하는 것은 중요

우리가 나중에 컴포넌트에서 props 가 바뀌지 않았으면 Virtual DOM 에 새로 렌더링하는 것 조차 하지 않고 컴포넌트의 결과물을 재사용 하는 최적화 작업을 할건데요, 이 작업을 하려면, 함수를 재사용하는것이 필수

함수 안에서 사용하는 상태 혹은 props 가 있다면 꼭, deps 배열안에 포함시켜야함
만약에 deps 배열 안에 함수에서 사용하는 값을 넣지 않게 된다면, 함수 내에서 해당 값들을 참조할때 가장 최신 값을 참조 할 것이라고 보장 할 수 없음
props 로 받아온 함수가 있다면, 이 또한 deps 에 넣어주어야함

useCallback, useMemo, Reacct.memo 는 컴포넌트의 성능을 실제로 개선할 수 있는 상황에서만 사용


useReducer

  • 상태관리할 때 useState를 사용하는 것 말고 다른 방법
  • useReducer 사용 시 상태 업데이트 로직을 컴포넌트에서 분리 가능

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;

Reference

velopert와 함께하는 모던 리액트, https://react.vlpt.us/basic/17-useMemo.html [Accessed: June.28]

https://velog.io/@velopert/react-hooks

profile
기억보단 기록을

0개의 댓글