useState에 초기값은 보통 바로 넣는다.
초기값이 array이라고 할지라도, new array가 return되기 때문이다.
const [list, setList] = useState(defaultList || []);
console.log(list === defaultList); // false
하지만 array의 value type이 primitive가 아닌 경우 문제가 된다.
string[]
: 문제 없음
object[]
: 문제 가능성 있음
예를 들면 setList로 list를 계속 업데이트 하다가, 마지막에 defaultList로 setList를 하고자 한다면, 내부에 있는 object값은 계속 reference되고 있는 상황이기 때문에, 최초의 defaultList가 되지 못한다.
따라서 array의 value type이 array
또는 object
인 경우에는 deep copy를 해야한다.
// shallow copy
let arry = [{ a: 'apple' }, { b: 'banana' }];
let copy = arry.map(item => item);
console.log(arry === copy); // false
console.log(arry[0] === copy[0]); // true
// deep copy
let deepCopy = arry.map(item => ({...item}));
console.log(arry === deepCopy); //false
console.log(arry[0] === deepCopy[0]); //false
결론으로 useState는 아래와 같이 되어야한다.
const deeplyCopyList = defaultList.map(item => ({...item});
const [list, setList] = useState(deeplyCopyList || []);