[React] useState, useReducer, 게으른 초기화

김건휘·2024년 4월 30일
1

React

목록 보기
1/19
post-thumbnail

☑️useState

🍀state란?


컴포넌트의 상태(컴포넌트가 가질 수 있는 상태)
ex) 시계라는 컴포넌트가 있다면, state로 time을 가질 수 있다.

🍀useState란?


컴포넌트의 상태를 간편하게 업데이트 해줄 수 있게 도구를 제공
ex) state: time = 5시 ⇒ state: time = 6시

🍀useState 문법


const [state, setState] = useState(초기값);

state 생성과 동시에 가져야 할 초기값을 useState 함수의 인자로 넣어주면, state와 setState라는 두가지 요소를 배열 형태로 return해준다.
현재 상태 값은 state 변수에 들어있고, state를 변경시켜주고 싶을 때는 setState를 이용해서 간편하게 변경 시켜줄 수 있다. 여기서 state와 setState의 이름은 마음대로 지정할 수 있다.

🍀간단한 예시


const [time, setTime] = useState(5);

⇒ State: time = 5 (time이라는 state가 초기값으로 5를 가진다.)

setTime(6);

⇒위와 같이 setTime함수 인자에 변경될 값을 넣어주면, State: time = 6으로 변경된다.

🍀구현 예시


//App.js

import { useState } from 'react';

function App() {
    const [time, setTime] = useState(1);

    const handleClick = () => {
        setTime(time +1);
    };

    return (
        <div>
            <span>현재 시간: {time}</span>
            <button onClick={handleClick}>Update</button>
        </div>
    );
}

export default App;

동영상링크

🍀useState 이점


  • 함수형 컴포넌트에서 상태 관리를 간소화 한다
  • 하나의 컴포넌트에서 여러 개의 상태 변수를 가질 수 있다
  • 상태를 다시 렌더링할 때 이전 상태를 유지한다
  • 상태가 변경될 때만 다시 렌더링을 트리거한다

🍀useState 사용시 주의사항


  • useState 호출에서 동일한 상태 변수 이름을 사용하면 ❌
  • useState에 초기값을 제공하지 않으면 ❌

☑️useReducer

🍀useReducer란?


useState와 마찬가지로 state를 생성하고 관리할 수 있게 해주는 도구

🍀useReducer vs useState(useState와의 차이점)


useState가 간단한 상태 업데이트에 적합하다면, useReducer는 상태 관리의 복잡성이 증가할 때 그 진가를 발휘합니다. 따라서, 상태 관리의 복잡성이 높아질 것으로 예상되거나 위에 언급된 상황에 해당될 때 useReducer의 사용

🍀useReducer 함수


import React, { useReducer } from "react";
const [state, dispatch] = useReducer(reducer, initialState, init);
  • state : 컴포넌트에서 사용할 상태
  • dispatch 함수 : 첫번째 인자인 reducer 함수를 실행시킨다, 컴포넌트 내에서 state의 업데이트를 일으키기 위해 사용하는 함수
  • reducer 함수 : 컴포넌트 외부에서 state를 업데이트 하는 함수, 현재 state와action 객체를 인자로 받아서 기존의 state를 반환하는 함수
  • initialState : 초기 state
  • init : 초기함수(초기 state를 조금 지연해서 생성하기 위해 사용)

⇒ 한마디로 말해, 컴포넌트에서 dispatch함수에게 action을 던지면, reducer 함수가 이 action에 따라 state를 변경해준다.

🍀useReducer 예제


const initialState = {count: 0};

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}

1) 플러스(+) 버튼 클릭시

  • dispatch가 reducer에게 action을 요구한다. (action = {type: ‘increment’})
  • action 객체의 type 속성값은 ‘increment’이므로, state는 1 증가한다

2) 마이너스(-) 버튼 클릭시

  • dispatch가 reducer에게 action을 요구한다. (action = {type: ‘decrement’})
  • action 객체의 type 속성값은 ‘decrement’이므로, state는 1 감소한다

🍀useReducer를 언제 사용하는게 좋을까?


  • 복잡한 상태 로직이 있는 컴포넌트
  • 상태를 공유하는 여러 자식 컴포넌트가 있는 경우
  • 성능 최적화가 필요한 경우
  • 액션을 기반으로 한 업데이트가 필요한 경우

☑️Lazy Initialization(게으른 초기화)


🍀Lazy Initialization(게으른 초기화)란?


게으른 초기화(lazy initialization)는 컴퓨터 프로그래밍에서 객체 생성, 값 계산, 또는 일부 기타 비용이 많이 드는 과정을 처음 필요한 시점까지 지연시키는 기법이다.
즉, 초기화 작업을 극한으로 미루다가 사용자가 필요로 할 때 진행

🍀Lazy Initialization(게으른 초기화)를 사용하는 이유는?


  • 메모리 낭비 감소
  • 퍼포먼스 향상
  • 성능 최적화

🍀Lazy Initialization 예시(useState)


<기존 코드>

import { useState } from 'react';

function App() {
  function initialState() {
    return 0;
  }

    const [count, setCount] = useState(initialState());

    return (
        <div>
            <h1>{count}</h1>
            <button onClick={() => setCount(count + 1)}>카운트올려</button>
        </div>
    );
}

export default App;
  • 버튼을 클릭 할 때마다(랜더링이 될 때마다), 함수가 담고 있는 우리가 만들어 놓은 모든 변수나 인자값들이 새로 만들어지고 값이 평가 ⇒ 불필요한 낭비 발생

<게으른 초기화 적용 코드>

import { useState } from 'react';

function App() {
  function initialState() {
    return 0;
  }

    const [count, setCount] = useState(() => initialState()); //수정된 부분

    return (
        <div>
            <h1>{count}</h1>
            <button onClick={() => setCount(count + 1)}>카운트올려</button>
        </div>
    );
}

export default App;
  • 콜백함수를 넣어주어 문제해결!
  • 함수를 만드는건 빠르다. 그 안에 아무리 비용이 많이 들어가는 작업이 들어있다 해도, 그 작업은 오로지 우리가 그 함수를 호출할 때에만 일어난다. 이제 React는 초기값이 필요할 때에만, 즉 최초로 컴포넌트가 랜더링 될 때에만 콜백함수를 호출하게 된다. 항상 바쁘게 랜더링이 일어나는게 아니라 필요할 때만 한번씩 나오기 때문에 '게으른'이라는 말이 붙게 된 것이다
profile
공유할 때 행복을 느끼는 프론트엔드 개발자

0개의 댓글