key 값을 넣어주지 않았기 때문에 에러가 발생한 것이다. 컴포넌트 안에서 리스트를 렌더링할 때는 꼭 key 값을 넣어줘야 한다.
💡 key 값의 데이터 타입은 상관 없다. 배열 안에서 유일한 값 뭐든지 가능하다. 동일한 컴포넌트 리스트에서만 ‘유일값’이면 된다.
💡 고유의 값을 찾을 수 없다면 인덱스를 key로 사용하면 되지만 단순히 에러를 제거하기 위한 미봉책일 뿐 권장하지 않는다. 그러나 데이터별 식별자는 반드시 존재하고 있다. 데이터베이스에 저장되는 데이터는 고유한 값을 넣어줘야 데이터를 구별하기 때문에 key 값으로 사용할 수 있는 ID가 반드시 존재한다.
const posts = [
{ id: 1, title: "Hello World", content: "Welcome to learning React!" },
{ id: 2, title: "Installation", content: "You can install React from npm." },
];
function Blog(props) {
const sidebar = (
<ul>
{props.posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
const content = props.posts.map((post) => (
<div key={post.id}>
<h3>{post.title}</h3>
<p>{post.content}</p>
</div>
));
return (
<div>
{sidebar}
<hr />
{content}
</div>
);
}
function App() {
return (
<>
<Blog posts={posts} />
</>
)
}
key 값을 넣어주는 이유: React에서 렌더링 작업을 진행했을 때 어떤 요소에 변동이 있다면 그 요소만 새로 그려주기 위해서 (무슨 컴포넌트인지 구분)
자식들이 key를 가지고 있지 않다면, 기존 트리와 비교해서 바뀐 부분부터 모두 새롭게 그리지만(-> 비효율적)
자식들이 key를 가지고 있다면, React는 key를 통해 기존 트리와 이후 트리의 자식들이 일치하는지 확인하고 달라진 부분만 바꿔준다.
💡 컴포넌트 리스트에 key 값을 넣어주면 reconciliation 프로세스를 최적화해준다
함수형 업데이트
React는 setState 함수의 호출이 일관성을 유지하기 위해서 내부적으로 동일한 내용의 state 함수 호출이 여러 번 반복되어도 하나의 업데이트로 취급하여 처리(마지막 업데이트만 적용)한다.
그럼 setState 함수를 여러 번 호출하면 어떻게 기존 트리와 이후 트리를 비교해서 처리할까?
함수형 업데이트를 사용하면 함수의 인자로 전달되는 state 값을 React가 이전 state의 값으로 보장한다. 그래서 상태 업데이트가 비동기적으로 처리된다(setState 함수: 비동기 함수)고 해도 안정적으로 기존 트리와 이후 트리를 비교하여 처리할 수 있다.setDatas( datas.filter((item) => { return id !== item.id; }) ); // 함수형 업데이트 // 콜백함수 인자에 이전 가상돔을 넣어주는 것을 React가 보장한다 setDatas((prevDatas) => { return prevDatas.filter((item) => { return id !== item.id; }); });
이전 상태를 조작해야할 경우 사용한다
function App() {
return (
<Hello/>
);
}
function Hello(props) {
const name = props.name;
if(name){
return <One name={name}/>
} else {
return <Two/>
}
}
function One(props){
return (
<div>
<h1>{props.name}</h1>
</div>
)
}
function Two(props){
return (
<div>
<h1>name이 입력된 것이 없습니다.</h1>
</div>
)
}
export default App;
true && <h1>hello world</h1> -> h1 출력
false && <h1>hello world</h1> -> false 출력
true || <h1>hello world</h1> -> true 출력
false || <h1>hello world</h1> -> h1 출력