function App() {
let [제목, 변경할제목] = useState( ['가시', '나무', '오렌지나무'] );
return (
<button onClick={ () => { ??? } }> 수정버튼 </button>
)
}
function App() {
let [제목, 변경할제목] = useState( [ '가시', '나무', '오렌지나무' ] );
return (
<button onClick={ () => {
변경할제목(['선인장', '나무', '오렌지나무']);
}> 수정 버튼 </button>
)
}
제목
이라는 state 값이 바뀌게 됩니다. state 변경 함수는 ( )
안에 넣은 걸로 기존 state를 갈아 치워주기 때문에 저렇게 집어넣으면 됩니다.변경할제목('선인장') 이라고 쓰면 state 안의 값은 '선인장' 이라는 값 하나만 남게 됩니다. 만약 배열로 적었다가 위와 같이 적게 되면 모든 내용이 깨지게 됩니다.
[ ]
안에 글이 3개 밖에 없기 때문에 할 수 있는거지 글이 100개 이상 들어있게되면 onClick 안의 코드도 매우 길어지게 될 것 입니다. function App() {
let [제목, 변경할제목] = useState( ['가시', '나무', '오렌지나무'] );
return (
<button onClick={ () => {
제목[0] = '선인장';
변경할제목(제목);
}} > 수정 버튼 </button>
)
}
제목
이라는 초기값을 다시 집어 넣은 것 입니다. 그런데 이 것보다도 더 좋은 방법이 있습니다.function App() {
let [제목, 변경할제목] = useState(['가시', '나무', '오렌지나무']);
return (
<button onClick={ () => {
let copy = 제목;
copy[0] = '선인장';
변경할제목(copy);
} } > 수정 버튼 </button>
)
}
array, object의 자료를 다를 때는 원본 데이터를 직접 조작하는 것 보다는 기존값은 보존해주는 식으로 코드를 작성하는 것이 좋은 관습입니다. (막상 변경했는데 원본 파일이 필요할 경우도 생길 수 있기 때문에)
그래서 let copy 같은 변수에다가 기존 array를 복사해놓고 그걸 조작하는 식으로 코드를 작성하면 조금 더 안전합니다.
하지만 위와 같이 코드를 작성하면 실제로는 변경되는 것이 없는 것을 확인하실 수 있습니다. 그게 State 함수의 동작원리 때문인데, 이유는 아래와 같습니다.
state 변경함수를 사용할 때 기존state === 신규state
이렇게 검사를 해보면 true가 나옵니다. 그러면 기존의 state와 같다는 뜻인데, 그 것 때문에 글제목 변경(copy)를 해도 변경된 값이 나오질 않는 것 입니다.
copy라는 변수가 기존 state와 같기 때문에 변경이 되지 않은 것 입니다.
copy라는 변수랑 기존 state랑 안에 있는 자료가 다른데 왜 같다고 할까요? 그 것은 array와 object의 동작원리 때문입니다.
자바스크립트를 예로 들어보기 위해 array/object를 하나 만들어봅시다.
let arr = [1,2,3]
이렇게 만들면 [1, 2, 3] 자료는 RAM 이라는 가상공간에 저장이되고, let arr 변수에는 그 자료가 어디있는지 가리키고 있는 화살표만 담겨있습니다.let data1 = [1,2,3];
let data2 = data1;
이런식으로 사용하면 복사가 됩니다. data1에 있던 자료를 data2에 복사한다는 뜻인데, data2를 출력해보면 [1, 2, 3] 이라는 값이 잘 나옵니다.
그런데 data1 과 data2는 각각 [1,2,3]이라는 데이터를 별개로 저장하는 것이 아니라 data1과 data2는 똑같은 값을 공유합니다. data1을 변경하면 data2도 자동으로 변경됩니다.
왜냐하면 변수에는 화살표만 저장되기 때문입니다. 그래서 방금 한 것은 화살표를 복사한 것이고, data1 과 data2는 똑같은 화살표를 가지게 되는 것 입니다. (같은 자료를 가리킴)
let copy = 제목;
copy[0] = '선인장';
변경할제목(copy);
이렇게 코드를 작성하게 되면 컴퓨터는 copy
와 기존 제목
의 state를 똑같다고 생각하기 때문에 state 변경을 해주지 않습니다.
그래서 해결 방법은 아래처럼 코드를 작성하면 됩니다.
let copy = [...제목];
copy[0] = '선인장';
변경할제목(copy);
let data1 = [1,2,3];
let data2 = [...data1];
console.log(data1 === data2); // false
리엑트에서 array/object를 수정하고 싶으면 독립적인 카피본을 만들어서 수정하는 것이 좋습니다.
[...기존state] or {...기존state} 이렇게 하면 독립적인 카피가 하나 생성됩니다.