지금까지 많은 값을 가지고 있는 state에 대해서는 컴포넌트 내에서 무조건 배열로 state를 관리했다.
import "./styles.css";
import React, { useState } from "react";
import Child from "./Child";
export default function App() {
const [state, setState] = useState([
{
id: 1,
name: "cheolsoo"
},
{
id: 2,
name: "hello"
},
{
id: 3,
name: "baekho"
}
]);
const update = (changedState) => {
setState((state) =>
state.map((item) => {
if (item.id === changedState.id) {
return { ...item, name: changedState.name };
}
return item;
})
);
};
return (
<div className="App">
{state.map((item) => (
<Child key={item.id} item={item} onUpdate={update} />
))}
</div>
);
}
//Child.js
import React from "react";
const Child = ({ item, onUpdate }) => {
const update = (e) => {
onUpdate({ id: item.id, name: e.target.value });
};
return <input type="text" value={item.name} onChange={update} />;
};
export default Child;
이렇게 하나의 배열을 state로 하고 각 배열의 원소에는 object를 가지고 있는 형태로 state를 만들어 이에 맞춰서 각 object를 props로 자식컴포넌트로 전달하려할 땐 map을 이용하여 배열을 리턴하였다.
그런데 만약 state를 업데이트 해야한다면? 심지어 업데이트도 굉장히 자주일어난다면? 심지어!! 배열의 길이가 100000개라면?? state를 배열로 관리하는것이 좋을까?
그렇지 않다.!!
update 함수를 보자.
state를 map으로 순회하는데 변경될 object를 발견하면 변경된 값(새로운 reference 를가지고있는 오브젝트)을 리턴하고 아니면 기존의 object를 리턴한다. 만약 배열의 길이가 100000개 라면 state를 업데이트하는 복잡도도 그만큼 증가할 것이다. (굳이 전부 순회할필요없잖아!?)
그래서 나온 생각이 state를 배열로써 관리하는게아닌 state로 관리하는 것이다.
import "./styles.css";
import React, { useState } from "react";
import Child from "./Child";
export default function App() {
const [state, setState] = useState({
1: {
id: 1,
name: "cheolsoo"
},
2: {
id: 2,
name: "hello"
},
3: {
id: 3,
name: "baekho"
}
});
const update = (changedState) => {
setState((state) => {
return { ...state, [changedState.id]: changedState };
});
};
return (
<div className="App">
{Object.keys(state).map((key) => (
<Child key={key} item={state[key]} onUpdate={update} />
))}
</div>
);
}
//Child.js
import React from "react";
const Child = ({ item, onUpdate }) => {
const update = (e) => {
onUpdate({ ...item, name: e.currentTarget.value });
};
return <input type="text" value={item.name} onChange={update} />;
};
export default Child;
위의 예제완 다르게 state가 object로 존재한다. id값을 key값으로 하는 오브젝트로써 존재한다.
그러기에 자식컴포넌트인 Child를 랜더링 할때 object를 순회하는 방법으론 map말고 Object.keys()를 이용해서 key를 빙긍빙글 돌며 자식컴포넌트인 Child컴포넌트를 정의하고있다.
state를 배열로 쓸때와 다르게 object를 이용하니 state 업데이트 할때 해당 id 의 object를 찾아서 바로바로 업데이트 할수있다. (map과는 다르게 불필요한 순회를 끝까지 할필요가 없다.!)
.
말고 [] 배열처럼 index로 접근가능 이는 해당 object의 key 와 value가 가변일때 접근하는 방법이다!return { ...state, [changedState.id]: changedState };