내가 헷갈려서 정리하는 React state 사용법

hyun·2021년 10월 30일
2

React

목록 보기
1/3
post-thumbnail

state

리액트에서는 중요한 데이터를 state에 담아서 보관하고 변경한다.

import React, { useState } from 'react';

let [data, setData] = useState(0);
data = 1; // 틀린 방법!
setData(1);

useState()는 state를 하나 만들어주는 함수이다. 이용하기 위해선 import해줘야 한다.
useState()안의 인자로 state를 초기화할 수 있다. useState(저장할 데이터) 이렇게 사용하면 state에 데이터를 저장할 수 있다.

useState를 사용하면 데이터가 [데이터1, 데이터2] 형식의 array로 2개가 생성된다. 이 데이터1, 데이터2 자리를 ES6 destructuring 문법을 이용해 저장해서 쓰는 것이 일반적이다.

데이터1에는 실제 저장되는 데이터가 들어있고, 데이터2에는 저장할 데이터를 변경해주는 함수가 들어있다. state는 직접적으로 값을 변경할 수 없기에 데이터2 자리에 들어가는 함수를 이용해서 값을 변경해 줘야 한다.

ES6 destructuring이 뭔데?
array에 저장된 데이터들을 변수로 쉽게 빼서 쓰고 싶을 때 사용하는 문법이다. 예를 들어

var array = ["kim", 20]
var name = array[0]
var age = array[1]

array에서 이름과 나이를 따로 빼서 사용하고 싶을 땐 이렇게 한다. 이걸 destructuring을 이용하면,

var [name, age] = ["kim", 20]

요렇게 된다.
왼쪽 오른쪽 형식을 똑같이 맞춰주면 알아서 들어간다.

state를 쓰는 이유

그냥 변수를 써도 되는데, 굳이굳이 복잡하게 state를 쓰는 이유가 뭘까?
변수와는 달리, state는 값이 변경될 때 자동으로 html이 재렌더링된다. 리액트는 state 값이 변경될 때 state가 포함된 html을 자동으로 렌더링해줘서 새로고침 없이 스무스하게 샤샥 변경이 된다(일반변수는 새로고침을 해야 변경이 된다).

그래서 변경이 자주 일어나는 데이터를 state에 저장하는 것이 좋다. 예를 들면 좋아요 버튼. 게시글에 좋아요를 눌렀을 때 새로고침을 해야 좋아요 하트가 빨갛게 변한다면 너무 구릴 것이다. 반대로 블로그 제목이나, 로고 같이 거의 변경이 일어나지 않는 데이터는 굳이 state를 사용하지 않아도 되겠다.

state값이 array/object일때 변경하는 방법

위에서 state의 값은 useState의 두번째 값인 함수로 변경한다고 했다.

let [value, setValue] = useState("데이터");
setValue("변경된 데이터");

그런데 state가 array나 object 자료형일 때는 저렇게 변경하면 안된다. 예를 들어, 배열의 첫번째 요소를 변경하는 코드를 살펴보자.

let [array, setArray] = useState(["하나","둘","셋"]);
setArray(["우왕", "둘", "셋"]);

잘 동작한다. state를 변경하는 함수는 state를 아예 대체할 수만 있다. 그래서 기존 state를 바꿔치기 해줄 수 있는 array를 넣어줘야 한다. 그런데 매번 저렇게 써주기 귀찮다. array가 길어지면 더 어려워질 것이다. 다른 방법으로 해 보자.

function updateArray(){
    var copy = array;
    copy[0] = "우왕";
    setArray(copy);
}

위 코드의 로직은 다음과 같다.
1. state는 수정할 수 없으므로 복사본을 만들어서 copy에 저장한 후,
2. copy의 0번째 요소를 "우왕"으로 변경하고,
3. 그걸 setArray에 넣어서 바꿔치기한다.

그런데 이렇게 하면 안된다.
그 이유는 자바스크립트에서 array나 object 자료형은 등호(=)로 복사하면 새로운 데이터가 생성되는 것이 아니라 값을 공유하기 때문이다.

예를 들면,

var a = [1,2,3];
var b = a;

a를 b에 복사하려는 의도로 작성된 코드이다. 그런데 a와 b는 별개의 [1,2,3]을 가지는 것이 아니라 똑같은 값을 공유한다. a를 변경하면 b도 변경되는 것이다.
그러면 state를 등호(=)로 복사하지 말고 완전히 개별적인 복사본을 만들어주면 된다. 그 방법은

var copy = [...array];

이렇게 하면 array와 똑같은 값이 개별적으로 copy에 복사된다. copy의 값을 변경해도 array와는 개별적인 배열이므로 array의 값은 그대로이다.

function updateArray(){
    // var copy = array;  이렇게 하지 말고
    var copy = [...array]; // 이렇게 하면 된다
    copy[0] = "우왕";
    setArray(copy);
}

spread 연산자
쩜쩜쩜(...) 이렇게 생긴걸 spread 연산자라고 한다. 얘도 마찬가지로 ES6 신 문법이다.
array나 object 왼쪽에 붙일 수 있고 중괄호나 대괄호를 벗겨주는 역할을 한다. 이름 그대로 spread, 펼쳐주는 역할이다. ...[1,2,3] 이렇게 하면 1,2,3이 되는 것이다.
array나 object를 deep copy할 때 많이 사용한다.

var arr = [1,2,3];
var copy = [...arr];

이렇게 하면 arr에 있던 데이터의 괄호를 벗긴 다음 다시 대괄호로 감쌌기 때문에 값은 같지만 별개의 배열이 copy에 저장되게 된다.

정리

  1. React에서 변경이 자주 일어나는 데이터는 state에 저장하자.
  2. state는 state 변경 함수를 이용해서 값을 변경한다.
  3. state 변경할 데이터가 array나 object인 경우 spread 연산자(...)를 이용해서 copy 후 state 변경 함수에다 넣어서 바꿔치기 한다.
profile
프론트엔드를 공부하고 있습니다.

1개의 댓글

comment-user-thumbnail
2021년 10월 30일

좋은 글이네요~

답글 달기