본문 바로가기
  • 프론트엔드 개발자 세오세오 | Frontend dev Seo
Learn to Code

[JS] React에서 배열인 state에 아이템을 추가하고 싶다면!? (concat()과 Spread Syntax)

by CEOSEO 2021. 5. 7.
728x90
반응형

 

 

코드스테이츠의 커리큘럼에서 드디어 프론트엔드의 꽃이라는 리액트에 돌입했다! 이전에 Pre course에서 만들었던 Twittler 앱을 리액트로 바꾸어 만들어보는 작업을 어제 진행했다. 

 

 

<Pre course 과제 모음>

2021.03.29 - [Learn to Code] - 코드스테이츠 Pre Course 회고 및 4개의 웹앱 과제 결과물

 

 

UI 요소가 굉장히 적은 단순한 앱이지만 그래도 나름 단일 책임 원칙(Single responsibility principle)을 머리속에 떠올리며 컴포넌트 단위로 코드를 짜나갔다. 그러던 중, 공식문서를 탐독했지만 찾을 수 없던 방법이 하나 있었는데, 배열인 state에 업데이트를 하려면 어떻게 해야 가장 잘 했다는 소문이 날까??!에 관한 것이었다.

 

그래서 열심히 구글링을 했고, 역시나 많은 선구자들이 같은 내용을 궁금해하며 정리해놓은 자료들을 찾을 수 있었다. 그래서 이번 포스트엔 찾아서 공부하고 내 Twittler 앱에 적용한 방식을 공유하려고 한다.

 

 

 

비도 오는 우중충한 날, 고급져보이는 컬러를 쓰고 싶었다

 

 

 

 

 

리액트 컴포넌트의 State 변경하기

 

리액트의 state는 컴포넌트 사용 중 컴포넌트 내부에서 변할 수 있는 값이다. 그러나, state에 변경을 주고자 할 때 아래와 같이 state를 직접 수정하는 것은 허용되지 않는다.

 

// 노노노
this.state.mood = 'happy'

 

 

state를 바꾸려면 항상 setState()를 사용해주어야 한다.

 

// 행복했다
this.setState( {mood: 'happy'} )

 

그런데 내가 Twittler를 만들면서 봉착했던 문제는, 바로 저 state의 값이 위 예제와 같이 단순한 스트링('happy')이 아니라 객체들이 들어간 배열이라는 점이었다. 이 state는 바로 트위틀러로 작성한 메시지들이었으며, 각 객체는 메시지 ID, 작성자명, 작성시간, 그리고 메시지 내용을 가지고 있다. 이 배열 state를 기준으로 화면에 트위틀러 메시지들을 그려준다.

 

그말은 즉, 새로운 메시지를 입력하면 그 새로운 메시지는 state에 있는 저 배열의 맨 뒤에 추가가 되어야 한다는 뜻이다. 이를 해결하는데 생각할 수 있는 가장 쉬운 방법은 push()를 하는 것인데, 이건 사용이 불가하다. 왜냐하면, push는 기존 데이터인 배열을 변경시키기 때문이다. 따라서, 생각할 수 있는 대안은 기존 state를 변경하지 않으면서 새로운 배열을 생성하여 리턴하는 것이었다. 그래서 concat()을 응용한다.

 

아래는 addFood() 메소드를 통해 배열인 state.favoriteFoods의 맨 뒤에 새로운 값을 추가하는 예제이다.아래 예제에서, state.value는 input element를 통해 받는 새로운 음식 이름이라고 가정한다. 

 

class BoyFriend extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: '',
      favoriteFoods: ["살치살", "삼겹살", "치킨"]
    }
  }
  
  ...
  
  addFood () {
    this.setState( state => {
      const favoriteFoods = state.favoriteFoods.concat(state.value)
      
      return { favoriteFoods }
    })
  }
  
  render() {
    return (
      ...
    )
  }
}

 

 

즉, 배열인 state에 새로운 값을 추가하고 싶을 땐:

 

1. 적당한 이름의 메소드를 만든다

2. 그 메소드 안에서 setState()를 호출한다

3. setState()의 인자로 state를 인자로 받는 콜백 함수를 부른다

4. 그 콜백 함수 안에서 기존 배열 state에 새로운 값을 추가하면서 새로운 배열을 리턴하는 concat을 사용하여 새 배열을 만든다

5. 배열을 리턴한다

 

 

 

추가: 함수 컴포넌트에서 Spread syntax로 추가하기

많은 분들이 이 포스트를 찾아주시는데, concat()도 물론 깔끔하고 좋지만 기왕 배우는거! 더 모던한 자바스크립트를 사용하고 싶으시다면 Spread syntax로 작성하시는 것을 추천드리고자 추가 예제를 더한다.

 

아래는 "가장 좋아하는 음식" 하나를 적어넣을 수 있는 input과, 음식을 적은 뒤 버튼을 누르면 컴포넌트의 "favoriteFoods" 상태가 변경되는 예시이다. Spread syntax를 사용했고, React function component로 작성했다.

 

import React, { useState } from 'react'

export default function boyfriend() {
  const [food, setFood] = useState('')
  const [favoriteFoods, setFavoriteFoods] = useState(["살치살", "삼겹살", "치킨"])

  const handleChange = (e) => {
    setFood(e.target.value)
  }
  
  const handleSubmission = () => {
    setFavoriteFoods(prevList => [...prevList, food])
  } 

  return (
    <div>
      <form onSubmit={handleSubmission}>
        <input type="text" placeholder="Favorite food" onChange={handleChange}/>
        <input type="submit"/>
      </form>
    </div>
  )
}

 

 

 

 

 

 

 

728x90
반응형

댓글