React에서 함수의 불변성

🐶·2021년 6월 11일
0

미니 과제

목록 보기
2/15

Reactjs를 사용하다보면, state 를 변경해야하는 일이 빈번하다. 왜냐하면, 리액트는 상태를 감시하고 있다가 변경된 상태에 따라 컴포넌트가 리 렌더링되기 때문!!!

트위터 스프린트에서 아래와 같은 중요한 문제에 부딪혔다.
랜더링되는 트위터 메세지(단일 메세지: 객체)들은 배열의 형태로 있고 그런데, 새로운 메세지가 입력될 때(=기존 배열에 요소를 추가할 때) 왜 push() 가 아닌, concat() 을 사용할까? 그 이유에 대해 알아보기 전에 자바스크립트의 기본으로 돌아갈 필요가 있다.


왜 상태변화를 줄 때에는 deep copy 방식을 사용해야 할까?

React 컴포넌트에서는 state 또는 상위 컴포넌트에서 전달받은 props의 값이 변경될 때 리렌더링을 하게 된다. 객체나 배열과 같은 참조타입의 자료형의 경우, deep copy를 하지 않으면 내부의 값이 변경되었을지 몰라도, 레퍼런스가 가리키는 곳은 동일하기 때문에 똑같은 값으로 인식한다. 그러므로, 리 렌더링을 하지 않게 된다. 이런 문제 때문에, 기존 값을 '복사하여' 새로운 객체나 배열로 만들어주어야 한다. 그래야 래퍼런스 주소가 바뀐 것을 인지하고 리 렌더링을 하게 된다.

새로운 값을 반환하는(deep copy가 가능한) 배열 메소드 종류

아래 메소드를 잘 사용하면 새로운 배열 객체 반환, 복제의 효과와 삭제의 효과를 나타낼 수 있다.

  • concat()
  • map()
  • filter()
  • slice()
  • spread 문법(...)

따라서 상태값을 변화시켜 리랜더링을 의도할 때에는 push(), pop(), shift(), unshift() 등의 가변성 있는 함수를 사용하면 안 된다. 사용하더라도 복사하고자 하는 배열을 spread나 slice등을 활용하여 복제를 해놓고 사용해야 한다.

실습에 응용해보자

1. 버튼 클릭 시 트윗 메세지 리스트에 새 메세지 추가 기능

const [newTweets, newTweetsAdded] = useState(dummyTweets); --> dummyTweets이라는 배열이 초기값인 newTweets이라는 상태(state)를 선언한 것.

그리고 그 상태를 변경하기 위해 newTweetsAdded() 함수 내에 전달인자로 tweet.concat(newTweets) 즉, concat 함수를 사용하여 newTweets(초기값: dummyTweets)에다가 tweet이라는 객체를 포함시켰다.

즉, 여기서 newTweetstweet.concat(newTweets)은 서로 완벽히 다른 배열이기 때문에(서로 참조하지 않기 때문에) 리액트에서는 래퍼런스 주소가 바뀐것을 인지하고 리 랜더링을 해준다.

2. 트윗 메세지 삭제버튼 클릭 시 해당 메세지 delete되는 기능

주석에도 썼다시피, 원래는 1. 여러 배열의 요소 중 객체의 id 값이delete를 클릭한 객체의 id와 일치하는 것의 인덱스를 찾고(findIndex 함수 사용) 2. 그 배열의 요소를 제거하려고 아래와 같이 splice 함수를 썼었으나,

const idx = newTweets.findIndex(i => i.id === el); //지우고자 하는 그 객체의 인덱스를 찾아서
newTweets.splice(idx, 1); //newTweets에서 해당 배열 지움

splice 함수는 가변성을 띄고 있어, 불변성 함수인 filter 함수를 사용하여 정정하였다.(그 객체의 id값과 일치하지 않는 것만 추림)

const restTweets = newTweets.filter(obj => obj.id !== el);
    newTweetsAdded(restTweets);

트위터 추가 & 삭제를 함수의 불변성 개념과 연관시켜 공부해보았다.
오늘 공부 끝 ~

profile
우당탕탕 개발일기📝🤖

0개의 댓글