Add : Mission 3 - 댓글 기능 구현
commit message를 남긴 후 push 해주세요.
constructor() {
super();
this.state = {
commentValue: '',
commentList: [],
};
}
- 우선, 부모 컴포넌트의 state에는 우리가 작성하고 있는 댓글값을 가져올 commentValue라는 key키와 댓글 submit시, 해당 글을 담아주는 배열인 commentList라는 key를 지정해주었다.
- commentList라는 배열을 만들어준 이유는 map이라는 배열 매서드를 사용하여 댓글을 업로드시켜줄것이기 때문이다.
handleCommentInput = e => {
this.setState({
commentValue: e.target.value, //이벤트가 실행되는 타겟 요소의 벨류값을 저장
});
};
- Mission 1 로그인창의 input에서 했던 것처럼 input 입력값을 state에 저장해준다.
1)<Textarea>
에 onChange이벤트 설정 (onChange={this.handleCommentInput})
2) handleCommentInput 함수로 input 입력값을 state에 저장
addComment = () => {
const { commentList, commentValue } = this.state; //구조 분해 할당
this.setState({
commentList: commentList.concat([commentValue]),
commentValue: '',
});
- 버튼 클릭하면 this.state의
commentList
에 value값 담기
1) 게시 버튼에는 onClick이벤트 (onClick={this.addComment})
2) 이벤트 발생 시 실행되는 함수 생성
- 게시' 버튼이 눌리는 순간에 this.state에 발생하는 것
1. `commentList` 라는 배열에 `commentValue`로 담아줬던 값들을 담아주는 동시에,
2. `commentValue` 값은 다시 아무것도 없게된다.
- (concat() :빈 배열에 입력한 값을 담은 배열을 붙인 결과가 된다.)
- javascript push()메서드와 비슷한 역할
javascript에서 보통 배열에 데이터를 추가할 때에는 push()메서드를 써주었기 때문에 이 방법으로 생각하고 있었는데
react에서는 state 내부의 값을 직접적으로 수정하면 절대로 안된다고한다.(불면성 유지)
하여, push, splice, unshift, pop 같은 내장함수는 배열 자체를 직접 수정하게 되므로 적합하지 않아
대신에 존의 배열에 기반하여 새 배열을 만들어내는 함수인 concat, slice, map, filter 같은 함수를 사용해야한다고 한다.
* push : 기존 배열 자체를 변경
* concat : 새로운 배열을 만들어줌
addCommEnter = e => {
if (e.key === 'Enter') {
this.addComment();
}
};
- textarea에 onKeyPress 이벤트걸어주기 (onKeyPress={this.addCommEnter})
- 게시 버튼(
<button>
)에 이벤트걸어주는 것이 아니라는 것을 확실히 하고 넘어가자- 이벤트에 해당하는 key값이 Enter이면 addComment 함수를 실행하도록(this.addComment())
<testarea>
-> <input>
& <form>
태그에 onSubmit이벤트<form className="feeds_upload_wright" onSubmit={this.addComment}>
{/* <i className="far fa-smile icon"></i> */}
<FontAwesomeIcon icon={faSmile} className="far fa-smile icon" />
<input
placeholder="댓글 달기..."
onChange={this.handleCommentInput}
></input>
<button type="submit">게시</button>
</form>
- 인스타그램 클론 할 때 많은 분들이 댓글입력창을
<textarea>
가 아닌<input>
으로 넣어주셨고 button에는 type속성을 submit으로 주고 감싸진 form 태그에 onSubmit이벤트를 걸어주는 쪽으로 많이 하셨다.- 이렇게 하면 엔터 쳤을 때의 이벤트를 따로 걸어주지 않아도 돼서 나도 아래처럼 코드를 수정해주었고, 필요 없는
addCommEnter
함수는 삭제해주었다
<form className="feeds_upload_comments">
<li>
<span className="comment_writer">yyeon_jju</span>
<span className="comment_content">너무 예뻐요~~</span>
</li>
{this.state.commentList.map((commentElement, idx) => { //⭐map() 메서드 활용⭐
return <li key={idx}>{commentElement}</li>;
})}
</form>
3번에서는 commentList라는 state에 배열 형태로 댓글의 value 값들을 담아주었다.
우리는 이제 댓글 창에 배열에 담긴 각각의 요소들을화 시켜서 return한 값을 렌더링시켜줘야한다.
배열의 요소들을 각각태그 안에 담아서 리턴시켜줘야 하기 때문에 요소들에 각각 접근하여 새로운 값으로 반환시키는 map()메서드를 활용하였다.
- 우리가 주의를 기울여야할 코드는 아래 두 줄 이다.<
- 우선 state에서commentList
에 접근해서 해당 배열을 사용해야 하기 때문에
-this.state.commentList.map((commentElement, idx)
이렇게 배열에 접근하여 배열의 요소들을 인자로 주었다.
- return할 값은 우리가 반환하고 싶은 태그와 넘겨받은 파라미터를 사용하여 표현해주었다.{this.state.commentList.map((commentElement, idx) => { return <li key={idx}>{commentElement}</li>; })}
위의 단계까지 실행하고 댓글을 submit하면,댓글 창에 잘 올라오긴하는데 input에 작성해준 값이 초기화되지 않고 계속 그대로 유지가 될 것이다. 해결하려면 어떻게 해야할까?
1) input를 입력하면 입력값을 담고, 댓글 업로드 후에는 비워주기 위해 this.state에 value : ''라는 초기값을 넣어주었다.(input의 초기 상태는 빈 문자열이기 때문이다)
- 우리는 input의 value값을 submit할 때 두가지 작업을 하고 싶다
1) 3번addComment 함수와 4번에서 작성해준 것 같이 input value값이 댓글 창에 올라가도록
2) input value값이 초기화되도록- 위의 이 기능은 각각 따로 실행되어야한다.
이를 위해 나는 input의value
라는 attribute를 통해서 input의 value값의 상태를 바꿔주기로했다
constructor() {
super();
this.state = {
commentValue: '',
commentList: [],
value: '',
};
}
2) input태그 내에 value라는 attribute에 this.state의 value라는 키값을 적용해주었다.
<input
placeholder="댓글 달기..."
onChange={this.handleCommentInput}
value={this.state.value}
></input>
3) input의 onChange 이벤트 실행 시 handleCommentInput에서 this.state.commentValue 뿐만아니라 this.state.value도 함께 값을 넣어주어야 한다.
handleCommentInput = e => {
this.setState({
commentValue: e.target.value, //⭐두 개의 state에 모두 입력값을 저장해주어야한다⭐
value: e.target.value, //⭐두 개의 state에 모두 입력값을 저장해주어야한다⭐
});
};
4) input입력값이 submit되는 순간 (1)입력값이 댓글창에 업로드되는 작업 & (2)화면에 보이는 value값이 초기화는 작업이 필요한다. (1)번은 3번에서 마무리되었었고 (2)번 작업은 간단하다.
addComment = e => {
e.preventDefault();
const { commentList, commentValue } = this.state;
this.setState({
commentList: commentList.concat([commentValue]),
commentValue: '',
value: '', //⭐this.state.value를 다시 빈 문자열로⭐
});
};