0%

react에서 useState로 배열 상태값 변경하기, spread syntax

react

react에서는 배열에 대해 useState가 동작하지 않는다?

react에서 아래와 같이 messages라는, 배열을 갖는 state를 변경하려고 시도하면 변경된 값이 반영안되는 것을 확인할 수 있습니다.
이럴 때는, spread 문법을 사용해서 상태값을 변경해주면 됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import React, { useState } from 'react';



export default function Chat(props) {
let [messages, setMessages] = useState(['test1', 'test2']);
function change(){
messages.push("test");
setMessages(messages);
}


return (
<div>
{
items.map((item, index) =>{
return (
<div key={index}>{item}</div>
)
}
}
</div>
)
}

해결방법

앞선 문제가 발생했을 때, setState를 할 때, 아래와 같이 spread syntax를 사용해주면 됩니다.

1
2
let messages_new = [...messages, "test"];
setMessages(messages_new);

spread 문법 (…message)

아래와 같이 변수명 앞에 … 이 붙는것을 spread syntax라고 합니다.

1
[...messages, "test"]

스프레드 구문, 전개 구문이라고도 부릅니다.
스프레드(…) 구문은 대상을 개별 요소로 분리합니다.
Spread 문법의 대상은 iterable(반복가능)이어야 합니다.
spread 구문에 대한 실행예제는 아래와 같습니다.

1
2
3
4
5
6
7
8
9
// ...[1, 2, 3]는 [1, 2, 3]을 개별 요소로 분리한다(→ 1, 2, 3)
console.log(...[1, 2, 3]) // 1, 2, 3

// 문자열은 반복가능.
console.log(...'Hello'); // H e l l o


// 이터러블이 아닌 일반 객체는 Spread 문법의 대상이 될 수 없다.
console.log(...{ a: 1, b: 2 });

let messages_new = […messages, “test”];의 의미

[…messages, “test”] 는 messages에 있는 배열요소들을 나누어,
새로운 배열에 각 요소들을 넣는다는 뜻입니다.
즉, messages = [‘test1’, ‘test2’]이므로,
let messages_new = [‘test1’, ‘test2’, “test”] 가 되는 것입니다.

useState가 동작하지 않는 이유

setState는 이전 상태와 값을 비교하여 값이 다를 경우에 DOM을 다시 redering을 해줍니다.
그런데 만일 아래와 같이 쓴다면,
setMessages에 전달할 messages의 값이 이미 바뀌어져서
동일해지기 때문에 DOM을 다시 redering하지 않습니다.

1
2
3
4
5
6
messages.push("test");

// setMessage를 call 하기 직전에,
// messages의 이전상태는 : ["test1", "test2" ,"test"]
// messages에 변경할 상태는 : ["test1", "test2" ,"test"]
setMessages(messages);

따라서 이전 상태와 변경할 상태를 다르게 하기 위해,
새로 배열을 만들어서(copy) 변경을 가한다음에 setMessages를 호출하도록 합니다.