Programing/React

React useState Hook 알짜만 빼먹기!

리커니 2022. 12. 8.
반응형

이번 포스팅에서는 React 에서 상태를 관리하는 State에 대해서 알아보겠습니다.

React 프로젝트가 없으신 분은 아래의 Link를 참고하여 프로젝트를 생성해주세요!

 

Link : https://aljjabaegi.tistory.com/655

 

Vite 기반 React Project 생성하기

Vite의 장단점 등에 대한 소개는 아래의 링크를 참조하세요! 1.Vite 소개 Link : https://vitejs-kr.github.io/ Vite Vite, 차세대 프런트엔드 개발 툴 vitejs-kr.github.io 2. Node.js 설치 시작하기를 보시면 Vite는 Node.js

aljjabaegi.tistory.com

 

1. State란?

State는 React의 핵심기능 중에 하나이며, 동적인 값을 처리할 때 사용하는 개념입니다.

정적인 화면이면 state를 사용할 이유가 없습니다. 

state를 갱신하게 되면 state를 사용하는 모든 요소가 리렌더링 되게됩니다.

 

2.State 사용방법

state를 어떻게 사용하는지 알아보도록 하겠습니다. Class 방식과 Hook state를 사용하는 방식이 어떻게 다른지도 알아보도록 하죠.

1초마다 시간을 갱신하여 표출하는 화면을 예를들어 보겠습니다.

 

2.1 class 방식에서의 state 활용

class방식에서는 constructor 내 this.state로 선언하여 관리를 하게 됩니다.

 

import React from "react";
class Clock extends React.Component{
    constructor(props) {
        super(props);
        this.state = {date: new Date()};
    }
    componentDidMount() {
        this.timerID = setInterval(() => {
            this.tick();
        }, 1000);
    }
    componentWillUnmount() {
        clearInterval(this.timerID);
    }
    tick() {
        this.setState({
            date: new Date()
        });
    }
    render() {
        return (
            <div>
                <h1>{this.state.date.toLocaleTimeString()}</h1>
            </div>
        )
    }
}

function App() {
  return (
    <div className="App">
        <Clock />
    </div>
  )
}

export default App

 

constructor 에서 {date: new Date()} 로 state를 초기화 해 줍니다. 그리고 componentDidMount 로 Clock 컴포넌트가 마운트 된 직후에 1초마다 tick 메소드를 호출하게 됩니다.

tick 메소드에서는 this.setState를 통해 state를 갱신하고 있죠.

componentWillUnmount 메소드는 컴포넌트가 마운트 해제되어 제거되기 직전에 호출되는 메소드로 타이머가 있을 경우 초기화 해주는 역할을 합니다.

 

 

페이지를 실행해보면 위와 같이 시간이 표출되며 시간이 1초마다 갱신되는 것을 확인하실 수 있습니다.

state를 선언하고 갱신만 하였는데 그 state를 사용하는 h1의 textContent 가 자동으로 갱신되는 것을 확인하실 수 있습니다.

 

이제 위의 코드를 Hook state를 사용하여 변경해보겠습니다.

 

2.2 Hook  state 활용 방식

useState의 사용법은 아래와 같습니다. useState를 호출하면 상태값과 그 값을 갱신하는 set함수를 반환합니다.

useState의 매개변수로 초기값을 설정할 수도 있습니다.

const [state명, set대문자State명] = useState(초기값);

위의 class 방식과 동일하게 동작하는 Component를 Hook 을 사용하여 구현하겠습니다.

import React, { useEffect, useState } from "react";
const Clock = (props) => {
    const [timer, setTimer] = useState(new Date());
    let TimerID = null;
    const tick = () => {
        setTimer(new Date());
    }
    useEffect(() => {
        TimerID = setInterval(() => {
            tick();
        }, 1000);
        return () =>{
            clearInterval(TimerID);
        }
    }, []);
    return (
        <div>
            <h1>{timer.toLocaleTimeString()}</h1>
        </div>
    );
};

function App() {
    return (
        <div className="App">
            <Clock />
        </div>
    );
}

export default App;

useState와 useEffect를 import 해주고,

useState를 통해 상태를 갱신할 timer와 그 값을 갱신하는 함수인 setTimer를 받습니다.

class 방식에서의 componentDidMount, componentWillUnmount 의 역할은 useEffect hook이 대신합니다.

( useEffect에 대해서는 다음에 포스팅에서 자세히 알아보도록 하겠습니다.)

 

2.3 class VS Hook 방식

예전의 React에서는 class를 사용해 Component를 생성했지만, Hook이 16.8 버전에 등장하면서

Function을 사용해 같은 기능을 구현할 수 있게 되었습니다.

Hook 이 왜 등장했고, Hook을 사용하는 것이 왜 좋은가에 대해서는 아래의 Link를 참고하세요!

 

Link: https://ko.reactjs.org/docs/hooks-intro.html#motivation

 

Hook의 개요 – React

A JavaScript library for building user interfaces

ko.reactjs.org

 

3. 최초 렌더링 시 state 지연 초기화

위의 Hook state를 활용한 방식에서 useState의 매개변수로 초기값을 설정할 수 있었습니다.

만일, 이 초기값이 고비용의 계산 결과라면 useState의 매개변수로 함수를 전달함으로써 지연 초기화를 할 수 있습니다.

 

const [state, setState] = useState(() => {
      const initialState = someExpensiveComputation(props);
      return initialState;
});

 

4. 이전 state 확인

useState를 통해 전달되는 set함수의 매개변수로 updater 함수를 전달하여 이전 값에 접근 할 수 있습니다.

 

const [state, setState] = useState(0);
setState(prevState => prevState + 1});

setState((prevState) => {
	return prevState + 1;
});

 

5. state 끌어올리기

동일한 state를 같은 레벨의 여러 컴포넌트에서 사용해야 할 경우

해당 컴포넌트들의 공통 Parent로 state를 끌어올려 활용합니다.

부모컴포넌트에 state를 생성하고, 자식들의 props로 전달합니다.

 

6. state 사용 시 주의점

6.1 state에 값을 직접 갱신하지 않는다.

state를 갱신할 때는 꼭 setState 함수를 사용해야만 합니다. state의 값을 직접 변경하는 경우 React의 비교로직이 정상동작 하지 않아 리렌더링이 발생하지 않을 수 있습니다.

복잡한 구조의 Object를 state로 활용해야 한다면 Spread syntax를 활용하여 객체를 복사한 후 setState의 매개변수로 전달하도록 합니다.

만일 state를 변경했는데도 리렌더링 되지 않는다면 state에 직접 접근해서 값을 바꾸지 않나 다시 한번 확인하세요!

 

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

const newState = {...state};
newState.a = 'b';

setState(newState);

 

Link : https://aljjabaegi.tistory.com/624

 

Javascript spread syntax 전개구문 알짜만 빼먹기! 간결한 코딩 방법

Javascript spread syntex 전개구문 알짜만 빼먹기! 간결한 코딩 방법 전개구문(Spread Syntax) 는 함수의 호출, 배열과 객체의 리터럴에서 사용됩니다. 함수호출과 배열의 리터럴에서 사용 시에는 Iteratorabl

aljjabaegi.tistory.com

 

6.2. setState는 비동기적으로 동작한다.

const Btn = (props) => {
    return <button {...props}>클릭</button>;
};

function App() {
    const [state, setState] = useState(0);
    const handleClick = () => {
        setState(state + 1);
    };
    return (
        <div className="App">
            <h1>{state}</h1>
            <span onClick={handleClick}>
                <Btn onClick={handleClick} />
            </span>
        </div>
    );
}

 

부모인 span 클릭과 자식인 Btn 컴포넌트 클릭 시 state값을 1 증가시키는 handleClick을 호출합니다.

예상한다면 한번 클릭 시 2씩 증가해야할 것 같지만 1만 증가하는 것을 확인하실 수 있습니다.

React는 브라우저 이벤트가 끝날 시점에 state를 일괄적으로 업데이트하기 때문입니다.

 

이 코드를 2씩 증가하게 만들기 위해서는 위에서 알아본 updater 함수를 활용 하여야 합니다.

 

const handleClick = () => {
    setState((prevState) => prevState + 1);
};

위와같이 handleClick 함수를 변경해주면 2씩 증가되는 것을 확인하실 수 있습니다.

 

왜 동기적으로 state를 업데이트 하지 않는지에 대해서는 아래의 Link를 참고하세요.

Link : https://ko.reactjs.org/docs/faq-state.html

 

컴포넌트 State – React

A JavaScript library for building user interfaces

ko.reactjs.org

 

6.3. 전역적으로 관리해야 하는 state 가 있다면?

Redux 라이브러리 사용을 고려해보세요. 필요하다면요!

 

Link : https://redux.js.org/

 

Redux - A predictable state container for JavaScript apps. | Redux

A predictable state container for JavaScript apps.

redux.js.org

 

7. state를 언제 선언하고 사용해야 하나?

Link : https://ko.reactjs.org/docs/thinking-in-react.html

 

React로 사고하기 – React

A JavaScript library for building user interfaces

ko.reactjs.org

위의 React로 사고하기 페이지를 보면 앱을 React로 어떻게 설계하는지에 대해 나와있습니다.

일련의 순서는 이렇습니다.

 

1. 목업과 데이터 확인

2. UI를 컴포넌트 계층구조로 나누기

3. 정적인 화면 만들기

4. 변경 가능한 state의 최소집합 찾아내기

5. state의 위치 설정

6. 역방향 데이터 흐름 추가하기

 

정적인 화면을 만든 후 동적으로 변경되야 하는 state의 최소 집합을 찾고,

state를 사용하는 컴포넌트들을 확인하여 state를 선언해야하는 적절한 위치를 설정하고,

하위에서 state를 변경해 주어야 하는 경우 props로 전달하여 state를 갱신 할 수 있도록 설정하면 됩니다.

 

8. 마무리

지금까지 React state에 대해서 알아보았습니다. 앞으로 부족한 내용을 추가하도록 하겠습니다.

도움이 되셨다면 아래 공감을 눌러주세요^^

반응형

'Programing > React' 카테고리의 다른 글

React useEffect Hook 알짜만 빼먹기!  (0) 2022.12.14
Vite 기반 React Project 생성하기  (0) 2022.11.08

댓글

💲 추천 글