리액트 useState 정리

버건디·2022년 8월 9일
0

리액트

목록 보기
5/58
post-thumbnail

🔻 만약에 게시판을 만든다고 가정했을때, 비슷한 형태의 글들을 레이아웃을 만든다고 가정해보자

이럴때 state라는 객체를 통해 useState() 함수를 사용한다.

- state란 ❓

  • state란 리액트에서 유동적인 데이터를 다루기 위한 컴포넌트 안에 있는 객체이다.
  • 변수는 변경되어도 재렌더링이 되지 않지만, state는 변경이 되면 재렌더링이 된다.
  • state가 변경되는 과정에 Virtual DOM이 생성되고, 이 Virtual DOM이 바뀐 부분을 감지하여 실제 DOM에 업데이트를 한다.
  • 리액트 안에 있는 useState() 함수는 이벤트에 의해 초기에 설정해놓은 state가 변경되면 다른 state로 값을 바꾸어준다.

만약 위에 있는 사진대로 useState 없이 코드를 짰다고 가정한다면

import './App.css';

function App() {

  let post = '블로그 글 제목';

  return (
    <div className="App">
      <div className='black-nav'>
        <h4>블로그</h4>
      </div>
      <div className='list'>
        <h4>글제목1</h4>
        <p>217일 발행</p>
      </div>
      <div className='list'>
        <h4>글제목2</h4>
        <p>217일 발행</p>
      </div>
      <div className='list'>
        <h4>글제목3</h4>
        <p>217일 발행</p>
      </div>
    </div>
  );
}

export default App;

이런식으로 코드가 만들어지는데, 이것은 효율성이 떨어진다.

useState를 사용하면 훨씬 더 효율적으로 코드를 작성할 수 있다.

useState 작성하는 방법은

let [초기state, state변경할함수] = useState('보관할 자료');

이런식으로 작성을 하면된다.

- ❗️ 자주 변경될 것 같은 HTML을 state로 만들어놓으면 된다 ❗️

만약에 위의 사진대로 state를 사용해서 작성을 하고 싶다면

import './App.css';
import { useState } from 'react';

function App() {

  let [글제목, 글제목변경] = useState(['글제목1', '글제목2', '글제목3']); // 배열활용

  return (
    <div className="App">
      <div className='black-nav'>
        <h4>블로그</h4>
      </div>
      <div className='list'>
        <h4>{글제목[0]}</h4>
        <p>217일 발행</p>
      </div>
      <div className='list'>
        <h4>{글제목[1]}</h4>
        <p>217일 발행</p>
      </div>
      <div className='list'>
        <h4>{글제목[2]}</h4>
        <p>217일 발행</p>
      </div>
      
    </div>
  );
}

export default App;

이런식으로 useState에 배열을 활용하여 작성을 하면 된다


❓ 그렇다면 state를 변경하는것은 어떻게 해야할까 ❓

글제목[0] 옆에 좋아요 버튼을 하나 만들어서 좋아요 버튼을 누를때마다 브라우저 창에 좋아요 갯수가 하나씩 늘어나는 기능을 구현해보자!

/* eslint-disable*/
import { useState } from "react";

function App() {
  let [글제목, 글제목변경1] = useState(["글제목1", "글제목2", "글제목3"]);

  return (
    <div className="App">
      <div className="black-nav">
        <h4>블로그</h4>
      </div>
      <div className="list">
        <h4>
          {글제목[0]} <span> 👍 </span> 0
        </h4>
        <p>217일 발행</p>
      </div>
      <div className="list">
        <h4>{글제목[1]}</h4>
        <p>217일 발행</p>
      </div>
      <div className="list">
        <h4>{글제목[2]}</h4>
        <p>217일 발행</p>
      </div>
    </div>
  );
}

export default App;

클릭을 할때마다 저 0부분이 1, 2, 3... 이런 식으로 숫자가 1씩 증가해주어야 하는것이니까 state로 만들어보자

let [좋아요갯수, 좋아요갯수변경] = useState(0); // state 부분 추가
<h4> {글제목[0]} <span> 👍 </span>{좋아요갯수} </h4> // 좋아요갯수 부분을 state로 지정

👍 을 클릭하면 {좋아요갯수} state가 1씩 늘어나는거니 onClick을 하면 저 state변경함수인 좋아요갯수변경()이 발생하도록 하자

<h4> {글제목[0]} <span onClick={() => {좋아요갯수변경(좋아요갯수+1)}}> 👍 </span>{좋아요갯수} </h4>

onClick= {} 안에는 무조건 함수가 들어가야하고, onClick 이벤트가 발생했을 때, 좋아요갯수변경 함수가 호출되도록 하였다. {좋아요갯수} 는 초기값이 0이 었지만, 좋아요갯수변경 함수로 인해 1씩 증가하게 된다!

❓ 그렇다면 '글제목1' 을 클릭했을 때, '글제목1 변경'으로 바꾸려면 어떻게 해야할까 ❓

<h4> <span onClick={() => {
            글제목변경(['글제목1 변경', '글제목2', '글제목3']);}}> {글제목[0]} </span> 
<span onClick={() => {좋아요갯수변경(좋아요갯수+1)}}> 👍 </span>{좋아요갯수} </h4>

이런식으로 작성을 해주어도 상관은 없지만, 이렇게 코드를 작성하면 확장성이 부족하다. 만약에 저 글제목들이 1000개라고 했을시에, 저 onClick안에 코드가 가독성이 떨어진다.

그렇기 때문에 스프레드문법을 사용해서 복사본을 하나 만들어준 후에, 저 [0]부분만 '글제목1 변경' 으로 바꾸어 주면 된다.

<h4> <span onClick={() => {
           	let copy = [...글제목];
            copy[0] = '글제목1 변경';
            글제목변경(copy);}}> {글제목[0]} </span> 
<span onClick={() => {좋아요갯수변경(좋아요갯수<+1)}}> 👍 </span>{좋아요갯수} </h4>

밑의 코드처럼 스프레드 문법으로 복사본을 만들어주는것이 아니라 일반적으로 그냥 복사본을 하나 만든다고 하면 작동을 하지 않는다. 왜일까?

<h4> <span onClick={() => {
           	let copy = 글제목; // 작동안함
            copy[0] = '글제목1 변경';
            글제목변경(copy);}}> {글제목[0]} </span> 
<span onClick={() => {좋아요갯수변경(좋아요갯수+1)}}> 👍 </span>{좋아요갯수} </h4>

이 부분을 알려면 state 변경 함수 원리와 배열 값의 원리를 알아야한다.

  • state 변경 함수를 사용할때, 리액트내에서 기존 state와 바뀐 state 가 같은지 먼저 검사를 해보고, 같다면 state 변경을 해주지 않는다.

  • 또한 배열은 원시 값이 아닌 참조 값을 갖는데, 밑의 사진처럼 arr안에 [1, 2, 3]의 값이 들어가는 것이 아니라, arr이 [1, 2, 3]의 값을 가지고 있는 주소를 참조하기만 한다.

let arr = [1,2,3];
let arr2 = arr; // 새로 만들어주는 것이 아니라 똑같은 주소를 참조하고 있음.
  • 그렇기 때문에 let copy = 글제목; 을 해도 새롭게 배열값이 만들어지는 것이 아니라 결국엔 둘은 똑같은 값을 가지고 있는 것이므로 state를 변경해도 적용이 되지 않는다.

❗️ 배열 형태의 state 값을 변경 해줄때는 무조건 스프레드 문법을 통해 새로운 복사본을 만들어주고 state변경함수를 실행하자 ❗️

profile
https://brgndy.me/ 로 옮기는 중입니다 :)

0개의 댓글