React의 불변성을 지키는 예시이다.
import React, { useState } from "react";
function App() {
const [dogs, setDogs] = useState(["말티즈"]);
function onClickHandler() {
// spread operator(전개 연산자)를 이용해서 dogs를 복사합니다.
// 그리고 나서 항목을 추가합니다.
setDogs([...dogs, "시고르자브종"]);
}
console.log(dogs);
return (
<div>
<button onClick={onClickHandler}>버튼</button>
</div>
);
}
export default App;
JS에만 익숙하면 현재 ["말티즈"]인 배열에 새로운 요소인 "시고르자브종"을 push메서드를 사용하거나, ["말티즈"][2] = "시고르자브종"
으로 넣으면 왜 안 되는지 궁금할 수 있다. 그렇게 넣고나서 setDogs(dogs)로 스테이트를 변화시켜주면 되는거 아닌가 하고 말이다.
결론부터 이야기하면, 이런식으로 state로 관리하고 있는 변수를 조작하거나 훼손하여, setState함수에 넣는 행위는 권장되지 않는다.
두 방식 모두 실제로 적용을 해보면 코드는 다음과 같다.
import React from "react";
import { useState } from "react";
function App() {
const [dogs, setDogs] = useState(["말티즈"]);
return (
<div>
{dogs}
<button
onClick={() => {
dogs.push("시고르자브종");
setDogs(dogs);
}}
>
눌러
</button>
<input
onChange={() => {
console.log(dogs);
}}
></input>
</div>
);
}
export default App;
일단 함수를 설명하자면, onClick이 적용된 버튼 태그를 클릭하면 dogs배열에 "시고르자브종"을 추가하여 setDogs의 인자로 들어가게 된다. 그리고 input태그에 변화가 생길 때마다 dogs변수의 상태를 console에 띄우게 된다.
state가 변할 때, 다시 랜더링 된다는 법칙에만 입각하면, "돼야하는거 아냐?"라고 생각할 수 있다. 하지만 되지 않는다. 일단 화면에 랜더링 되는 {dogs}
부분은 무슨 짓을 해도 변하지 않는게 당연하고, 신기하게도 버튼을 클릭한 후에 input칸에 변화를 주면, console상으로는 변화가 인식된다. 다시 말해 추가된 배열을 나타낸다는 것이다.
하지만 권장되지 않음에도 어떨 때는 작동한다는 것이 열받는 점인데 그러한 예시는 다음과 같다.
import React from "react";
import { useState } from "react";
function App() {
let [dogs, setDogs] = useState("말티즈");
return (
<div>
{dogs}
<button
onClick={() => {
dogs = "시고르자브종";
setDogs(dogs);
}}
>
눌러
</button>
<input
onChange={() => {
console.log(dogs);
}}
></input>
</div>
);
}
export default App;
이번에는 state로 관리되고 있는 변수가 원시데이터인 경우이고, 또 바뀐 점은 state선언을 const가 아닌 let으로 하고 있다는 점이다.
보다시피 되긴 한다.
하지만 권장되지 않는다는 것은 분명하다.
리액트를 공부하는 교재에서 나름의 설명을 찾을 수는 있는데 이유는 다음과 같다.
"순수함수"라는 개념이 있다. 하나 이상의 인자를 받고, 인자를 변경하지 않고, 참조하여 새로운 값을 반환하는 함수를 말한다.
순수함수의 예시는 다음과 같다.
// 매개변수를 복사한 값을 변경하는 순수함수
const addSixPure = (arr) => {
// 펼침 연산자로 새로운 배열에 6 추가
newArr = [...arr, 6];
return newArr;
};
순수함수가 아닌 것의 예시는 다음과 같다.
const num_arr = [1, 2, 3, 4, 5];
// 매개변수의 값을 직접 변경하는 불순함수
const addSixImpure = (arr) => {
// 매개변수에 직접 6 추가
arr.push(6);
return arr;
};
결론만 말하자면,