코드스테이츠의 커리큘럼에서 드디어 프론트엔드의 꽃이라는 리액트에 돌입했다! 이전에 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>
)
}
'Learn to Code' 카테고리의 다른 글
Redux 기본 개념 정리 (4) | 2021.05.16 |
---|---|
[React] React Router 아주 쉽게 연습하기! (0) | 2021.05.16 |
[TIL] node.js 미니 서버 만들기 (0) | 2021.04.30 |
[TIL] 코드스테이츠 chatterbox (client) 과제 (ongoing) (0) | 2021.04.29 |
[JS] 자바스크립트로 구현하는 그래프(Graph), 인접행렬(Adjacency Matrix), 인접리스트(Adjacency List) (0) | 2021.04.23 |
댓글