불변성: 변하지 않는 성질
리액트에서의 불변성: 객체/배열을 수정할 때 기존 객체/배열을 건드리지 않는 것
❌ 불변성을 어기며 객체를 수정한 예시
const data = {id:1, text:'hello'};
const sameData = data;
sameData.text = 'bye';
console.log(sameData===data); // true
sameData와 data는 같은 객체를 가르키고 있다. 따라서 sameData.text
는 기존 객체인 data를 직접 수정하게 된다. 즉, 불변성을 어겼다.
⭕️ 불변성을 지키며 객체를 수정한 예시
const data = {id:1, text:'hello'};
const nextData = {...data, text: 'bye'};
console.log(nextData===data); // false
spread문법을 이용해 data객체의 내용을 복사해온 다음 text값을 새로운 값으로 덮어씌운 것이다. 즉 기존 개체는 건들지 않았다.
push, splice 함수는 모두 배열을 직접 수정한다. 배열의 불변성을 지키기 위해서는 배열 내장 함수들을 활용해야 한다.
const numbers = [0,1,2];
const nextNumbers = [...number, 3];
const numbers = [0,1,2];
const nextNumber = numbers.concat(3); // [0,1,2,3]
const nextNumber2 = numbers.concat([3,4,5]); // [0,1,2,3,4,5]
배열 내장 함수 filter
: 특정 조건을 만족하는 원소들로 이루어진 새로운 배열을 리턴해준다.
const numbers = [-3,-2,-1,0,1,2,3];
const filtered = numbers.filter(num => num>0);
// [1,2,3]
const filtered2 = numbers.filter(num => num!=0);
// [-3,-2,-1,1,2,3]
const filtered3 = numbers.filter((item,i) => i!=1);
// [-3,-1,0,1,2,3]
const items = [{id:1}, {id:2}, {id:3}];
const filteredItems = items.filter(item => item.id!=1);
// [{id:2}, {id:3}]
배열 내장 함수 map
: 기본적으로 배열 안의 모든 값을 수정한다. 삼항연산자를 활용하면 배열 안의 일부 값만을 수정할 수 있다.
const numbers = [-3,-2,-1,0,1,2,3];
const nextNumbers = numbers.map(number => number==0 ? 10 : number);
// numbers배열의 모든 원소를 차례로 number라는 이름의 인자로 받아온다.
// 인자가 0인 경우 10을 리턴 즉 10으로 수정, 0이 아닌 경우 본래 값을 그대로 리턴
여러 객체로 이루어진 배열을 수정할 때에도 마찬가지다. 다만 주의해야할 점은 객체를 수정할 때 꼭 불변성을 지켜주어야 한다는 것!
const items = [
{id:1, text:'hello'},
{id:2, text:'bye'},
];
const nextItems = items.map(item => item.id==1 ? {...item, text:'hi'} : item);
console.log(items[0]); // {id:1, text:'hi'}