댓글기능을 만들던 도중 console창에 다음과 같은 경고가 나왔다.
이 경고의 의미는 무엇이고 어떻게 해결해야 하는지 알아보자.
우선, 내가 짠 코드를 확인해보자.
<Feeds.js>
import React, { Component } from 'react';
import Comment from './Comment/Comment';
import './Feeds.scss';
class Feeds extends Component {
constructor(props) {
super(props);
this.state = {
comment: '', // input에서 입력하는 댓글 저장
comments: [], // 게시버튼을 누른 후 댓글들이 하나하나의 배열이 됨.
};
}
handleComment = e => { //댓글창에서 쓴 코멘트를 저장해주는 함수
this.setState({
comment: e.target.value,
});
};
pressButton = () => { //'게시'버튼을 누르면 댓글이 올라가는 함수
this.setState({
comments: this.state.comments.concat({
text: this.state.comment,
}),
});
};
render() {
return (
<ul className="comment_list"> //댓글 리스트
{this.state.comments.map(t => {
return <Comment text={t.text} />;
})}
</ul>
<div className="push_comment">
<div className="push_comment_text">
<input //댓글을 입력하는 곳
onChange={this.handleComment}
className="input_comment"
type="text"
placeholder="댓글달기..."
/>
</div>
<div className="push_comment_button"> //댓글 버튼
<button onClick={this.pressButton}>게시</button>
</div>
</div>
</article>
</div>
);
}
}
export default Feeds;
this.state.comment에 input에서 입력하는 댓글정보를 받게했다.
그다음 게시버튼을 누르면 comment에서 입력한 댓글이 배열인 comments안에 객체형태로 들어가게 했다.
ex[{text: '안녕하세요'}]
이렇게 하면 여러개의 댓글을 추가했을 때 this.state.comments의 상태는
ex)[{text: '안녕하세요'}, {text: '반갑습니다'},{text: '안녕히가세요'}]
위와 같은 형태 일 것이다.
<ul className="comment_list"> //댓글 리스트
{this.state.comments.map(t => {
return <Comment text={t.text} />;
})}
</ul>
<Comment.js>
import React, { Component } from 'react';
class Comment extends Component {
render() {
return <li>{this.props.text}</li>;
}
}
export default Comment;
그다음 배열 안에 담긴 객체들을 JSX형식으로 가공하고 나열하기 위해서 Array.map을 사용한다.
댓글 하나하나는 재사용할 UI이니 Comment라는 컴포넌트로 만들어준다.
그리고 객체(t) 안의 댓글내용(text)를 Comment 컴포넌트에 props값으로 넘기고 <li> </li>에 넣었다.
여기까지 하고 실행을하면 맨 위에서 만난
다음과 같은 에러가 발생하는 것이다.
이 에러가 발생하는 이유는 배열 안에 담긴 하나하나의 값이 고유한 키 값을 가지고 있지 않았기 때문이다.
어째서 Key값이 필요할까?
1.Key값은 React가 어떤 항목을 변경,추가,삭제할지 식별하는 것을 돕는다.
2.Key값은 배열안에 담긴 엘리먼트에 안정적인 고유성을 부여하기 위해서도 필요하다.
그런고로 키값을 줘보자.
<ul className="comment_list"> //댓글 리스트
{this.state.comments.map(t => {
return <Comment key={this.state.comments.length} text={t.text} />;
})}
</ul>
처음에는 '어? 그러면 그냥 comments길이를 키값으로 주면 첫번째는 1 두번째는 2로 나오겠네~'라고 생각해서 다음과 같이 했다.
하지만 이렇게 하니 키값이 중복된다고 경고메시지가 떴다.
생각해보니 당연했다. this.state.comments에 값이 추가되었을 때 render가 다시 호출되는데 그러면 배열의 길이가 최신상태니까 모든 키값이 같은 길이를 갖게 되는 것이다...
그래서 각각의 객체 안에 text값 뿐만이 아니라 id값도 넣어서 해결하기로 했다.
import React, { Component } from 'react';
import Comment from './Comment/Comment';
import './Feeds.scss';
class Feeds extends Component {
constructor(props) {
super(props);
this.state = {
comment: '',
comments: [],
idvalue: 0, // 아이디값을 추가.
};
}
handleComment = e => {
this.setState({
comment: e.target.value,
});
};
pressButton = () => {
this.setState({
comments: this.state.comments.concat({
id: this.state.idvalue, // 객체 안에 id값 저장
text: this.state.comment,
}),
});
this.state.idvalue += 1; //게시버튼을 누를 때 마다 idvalue값 1증가
};
render() {
return (
<ul className="comment_list">
{this.state.comments.map(t => {
return <Comment key={t.id} text={t.text} />; //key={t.id}추가
})}
</ul>
<div className="push_comment">
<div className="push_comment_text">
<input
onChange={this.handleComment}
className="input_comment"
type="text"
placeholder="댓글달기..."
/>
</div>
<div className="push_comment_button">
<button onClick={this.pressButton}>게시</button>
</div>
</div>
</article>
</div>
);
}
}
export default Feeds;
this.state에 idvalue값을 추가하였다.
그 다음 객체 안에 id키를 만들어서 그 값으로 this.state.idvalue를 넣었다.
게시버튼을 누를 때마다 idvalue값이 +1씩 증가함으로 키값의 고유성이 보장된다.
ex)
안녕하세요
[{id: 0 ,text: "안녕하세요"}] // 여기서 0은 idvalue의 기본값
idvalue:1 <- 게시버튼을 눌렀으니 +1
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
ex2)
안녕하세요
반갑습니다
[{id: 0 ,text: "안녕하세요"}, {id: 1, text: "반갑습니다"}]
idvalue:2
이렇게 한 후 실행하니 key값 문제가 해결되었다!!
'React > Today I learned' 카테고리의 다른 글
[React] 비동기, 동기 (0) | 2021.06.27 |
---|---|
[React] why react?, JSX, Node.js, CRA (0) | 2021.06.27 |
Class 컴포넌트 Constructor에서 super(props)를 써야하는 이유 (0) | 2021.06.23 |
생활코딩 React 11. 컴포넌트 만들기 (0) | 2021.06.22 |
생활코딩 React(리액트) 07~09 코딩,배포하는 방법 (0) | 2021.06.21 |