const movies = [
{name: 'supermario', date: new Date()},
{name: 'jurassicPark', date: new Date()}
];
function App() {
const [state, setState] = useState(movies);
const updateState = () => {
// 상태 업데이트 로직 들어가는 곳
};
return (
<div>
<button onClick={() => updateState()}>
button
</button>
</div>
);
}
const updateState = () => {
setState([...state, {name: 'supermario', date: new Date()}]);
};
위 코드는 배열 상태에 새로운 객체를 추가하는 기능을 하고 있다.
새로운 요소를 추가하는 식으로 상태를 업데이트하는게 아니라
기존의
{name: 'supermario', date: new Date()}
배열 안의 위 객체를 수정해주려면 어떻게 해야할까 생각해보게 되었다.
state[1].name = 'supermario-1000';
위 방식으로 수정해준다면 상태를 사실 업데이트하는게 아니게 된다.
상태의 업데이트는 이전 상태와 새로운 상태의 주소 값을 비교하여 다르면 업데이트가 되는 방식으로 작동하게 되어있는데 상태의 주소는 같으므로 리렌더링 예약이 되지도 않아 상태 값을 변경해줘도 리렌더링이 일어나지않게 된다.
const newState = [...state]; // 새로운 배열 생성
newState[0] = {name: 'supermario-1000', date: new Date()}; // 새로운 객체 할당
setState([...newState]);
const newState = movies.map((movie, index) => {
if (movie.name === 'supermario')
movie = {name: 'supermario-1000', date: new Date()};
return movie;
});
setState(newState);
map
메서드는 새로운 배열을 리턴하므로 이 배열은 상태와는 다른 주소 값을 가지고 있다.
리액트에서는 주소 값이 다르면 상태가 업데이트 되었다고 판단하므로 map 메서드를 사용하는 것은 적합하다.