이번에는 숫자를 기록한 것을 누적해서 보여준다고 해보자. 그렇다면 state recordNum를 배열로 만들면 될 것이다. 그리고 기록버튼을 누르면 push()함수를 이용해서 배열이 추가되는 방식을 사용하면 되지 않을까??
코드를 그렇게 작성해보자.
const App = () => {
const [num, setNum] = useState(100);
const [recordNum, setRecordNum] = useState([]);
return {
<button
onClick={() => {
recordNum.push(num); /*push함수로 배열에 현재 num을 집어넣고*/
setRecordNum(recordNum); /*그 배열을 다시 넣는다.*/
}}
>
{/*기록 버튼을 누르면 setRecordNum함수를 이용해 recordNum의 값을
현재 num으로 변경해준다.*/}
기록
</button>
<hr />
<div>
기록된 숫자 : {recordNum}
</div>
{/*변수 RecordNumber를 데이터 바인딩한다.*/}
</>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
하지만 이렇게 하면 안된다. 물론 로직적으로는 아무 문제가 없어보이지만 여기서 우리가 useState에서 불변성을 지켜야 하는 이유가 생긴다.
리액트는 상태가 바뀌었는지 비교를 통해 확인한다. 하지만 우리가
[recordNum, setRecordNum] = useState([]); 여기서 실제 값인 recordNum을 직접 push함수를 이용해 수정하고 setRecordNum를 이용해서 다시 recordNum를 집어넣게 된다면 리액트는 "상태가 바뀌지 않았다"고 생각한다. 그래서 우리는 새로운 객체나 배열을 만들어서 그 값을 집어넣어야 한다.
우리가 그래서 새로운 배열을 만들 때, 기존의 값을 표현하기 위해서 전개구문을 사용한다.
이번에는 이 기록된 숫자들의 형식 UI를 바꾸어 볼건데 map()이라는 함수를 활용할 것이다.

map() 함수는 각 요소를 차례대로 돌아가면서 실행해서 적용한 결과를 모아 새로운 배열을 만들어내는 함수이다. 원본 배열은 변경되지 않는다. 각 요소를 바꾸나 가공한 결과를 적용할 새로운 요소로 배열을 생성하기 위해 사용된다.
map() 함수를 시각화하면 다음과 같다.
[a, b, c, d].map(소문자 → 대문자) 👉 [A, B, C, D]
기본 형식은 이렇다.
arr.map(function(currentValue[, index[, array]]) { // 변환(mapping)할 로직: 변환된 결과를 반환해야 합니다. }); //또는 arr.map((element[, index[, array]]) => { /* … */ })
- currentValue (필수): 처리할 현재 요소. 이 매개변수를 통해 현재 요소에 접근할 수 있습니다.
- index (옵션): 처리할 현재 요소의 인덱스. 이 매개변수를 사용하여 현재 요소의 인덱스에 접근할 수 있습니다.
- array (옵션): map() 함수를 호출한 배열. 이 매개변수를 사용하여 원본 배열에 접근할 수 있습니다.
위 형식은 ul -> li 형식이기 때문에
<ul>
{ arr.map( element => <li> { element } </li>) }
</ul>
이런 형식을 띄면 된다.