useState, useReducer 와 useRef 용례, 그리고 Best Practice 모으기

재우·2023년 8월 26일
0
post-thumbnail

useState, useReducer, useRef는 React 라이브러리에서 제공하는 Hook 중 일부이다.

Hook 이란?

  • 함수형 컴포넌트에서 상태(state)와 생명주기 기능을 관리하기 위한 함수
  • 클래스 컴포넌트에서는 주로 생성자에서 state를 정의하고 setState 함수를 통해 상태를 업데이트한다. 하지만 기존 함수 컴포넌트는 이러한 state를 정의해서 사용하거나 컴포넌트 생명주기에 맞춰 실행 되도록 할수 없기 때문에 나온것이 바로 훅(Hook)이다.



useState

  • React Hook 중 하나로, 함수형 컴포넌트 내에서 상태(state)를 관리할 수 있게 해주는 기능이다.
  • 이 Hook을 사용하면 클래스 컴포넌트의 this.statethis.setState와 유사한 기능을 함수형 컴포넌트에서 간편하게 사용할 수 있다.
  • useState는 배열을 반환하며, 첫번째 요소에는 현재 상태값이, 두번째 요소에는 상태를 업데이트하는 함수가 포함된다.

import { useState } from 'react';
: useState를 사용하기 위해서는 react에서 useState를 import 해야한다.

const [time, setTime] = useState(1);
: state의 생성과 동시에 가져야 할 초기값을 useState 함수의 인자로 넣어주면 state와 setState라는 두가지 요소를 배열 형태로 리턴해준다. state명은 알맞게 설정하면 되고 두번째 요소에 set을 붙여주면된다.



const onChange = (e) => { setText(e.target.value); }
: 이벤트가 일어나는 타겟의 value를 text 값으로 업데이트
const onReset = () => { setText(''); }
: text 값을 ''공백으로 업데이트
<input onChange={onChange} value={text} />
: input 태그에 onChange 이벤트를 등록하고 value 값으로 text 상태 값을 준다. value 값을 설정해주지 않으면 상태가 바뀌었을때 input 내용이 업데이트 되지 않는다.




useRef

useRef는 저장공간(변수 관리), DOM 요소에 접근을 위해 사용되는 React Hook이다.


1. 저장공간(변수 관리)

  • React 컴포넌트는 State가 변할때마다 다시 렌더링이 되면서 컴포넌트 내부 변수들이 초기화 되고 내부 모든 로직등이 다시 실행된다.
  • 하지만 Ref안에 값을 저장하면 값을 아무리 변경해도 다시 렌더링 되지 않는다. 즉 컴포넌트가 아무리 렌더링이 되어도 Ref안에 저장되어 있는 값은 변경되지않는다.

State의 변화 ➡ 렌더링 ➡ 컴포넌트 내부 변수들 초기화
Ref의 변화 ➡ 렌더링 ➡ 변수들의 값이 유지됨
State의 변화 ➡ 렌더링 ➡ 그래도 Ref의 값은 유지됨


2. DOM 요소에 접근
대표적으로는 input요소를 클릭하지 않고 포커스를 주고 싶을 때 많이 사용한다. 예를 들어 로그인 화면이 보여줬을 때 id를 넣는 input을 굳이 클릭하지않아도 자동적으로 포커스가 되어있게 해줌.

  • 페이지가 로드 되면 useEffect Hook에 의해 input 태그에 자동 포커싱 된다.
  • useEffect()는 컴포넌트가 렌더링 될 때마다 특정 작업을 실행할 수 있도록 하는 Hook이다.
  • Ref는 input태그를 가리킨다고 볼 수 있다.



useReducer

state를 관리하고 업데이트하는 hook인 useState를 대체할 수 있는 hook이다. 즉, useReducer는 useState처럼 state를 관리하고 업데이트 할 수 있는 hook이다.

  • useReducer를 사용하게 되면 컴포넌트와 상태 업데이트 로직을 분리하여 컴포넌트 외부에서도 상태 관리를 할 수 있습니다. 즉, 하나의 컴포넌트 내에서 state를 다루는 로직을 분리하여 외부에서 처리할 수 있도록 해준다.

useState 만으로 상태 변화 로직을 만들면, 상태 변화 함수를 컴포넌트 안에서 작성해야 했다. 일반적인 방법이지만 관리해야 하는 상태 값이 많아지고 구조가 복잡해지면 useReducer를 사용하는게 깔끔할 수 있다.


userReducer 를 사용하면, 컴포넌트 외부에 상태 관리 로직이 있다.



useReducer 문법

const [state, dispatch] = useReducer(reducer, initialState);
  • state : 컴포넌트에서 사용할 상태 (useState의 state와 동일)

  • dispatch : dispatch({ type: "descrement" });

    • reducer 함수를 실행 시키며, 컴포넌트 내에서 state의 업데이트를 다루기 위해 사용.
    • 현재 정의되어있는 reducer 함수를 실행 시키며 dispatch는 함수의 인자로 업데이트 하기위한 정보를 가진 action을 사용한다.
  • reducer : 컴포넌트 외부에서 state 를 업데이트 하는 로직의 함수 ( reducer 함수는 state, action 객체를 인자로 받는다)

  • initialState : 초기 state (useState의 초기 할당 값과 동일)


reducer()

  • dispatch 함수에 의해 실행되며 컴포넌트 외부에서 state를 업데이트 하는 로직을 담당한다.
  • 현재 상태와 액션 객체를 파라미터로 받아와서 새로운 상태를 반환해주는 함수이다.
  • reducer가 반환하는 값이 곧 컴포넌트가 지닐 새로운 상태이다.
  • 함수 내에서 if-else를 사용해도 되고 switch를 사용해도 된다.
// reducer 함수 예시

export function reducer(state, action){
	//새로운 상태를 만드는 로직
  	switch(action.type) {
      case : "descrement" :
// action의 type이 "decrement"일 때, 현재 state 객체의 number에서 1을 뺀 값을 반환
      return state - 1;
      case "increment" :
// action의 type이 "increment"일 때, 현재 state 객체의 number에서 1을 더한 값을 반환
      return state + 1;
      default:
        //정의되지않은 action type이 넘어왔을 때는 에러를 발생시킴
      throw new Error("Unsupported action type:", action.type);
    }
  return nextState;
}
  • state : 현재 상태
  • action : 업데이트를 위한 정보를 가지고 있다. 주로 type 값을 지닌 객체 형태로 사용한다. ( { type : "decrement" } )

https://codesandbox.io/s/usereducer-forked-2twpv5?file=/src/App.js

0개의 댓글