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 값들을 담아주었다.
- 우리는 이제 댓글 창에 배열에 담긴 각각의 요소들을
<li>
화 시켜서 return한 값을 렌더링시켜줘야한다.- 배열의 요소들을 각각
<li>
태그 안에 담아서 리턴시켜줘야 하기 때문에 요소들에 각각 접근하여 새로운 값으로 반환시키는 map()메서드를 활용하였다.
- 우리가 주의를 기울여야할 코드는 아래 두 줄 이다.
- 우선 state에서commentList
에 접근해서 해당 배열을 사용해야 하기 때문에
-this.state.commentList.map((commentElement, idx)
이렇게 배열에 접근하여 배열의 요소들을 인자로 주었다.
- return할 값은 우리가 반환하고 싶은 태그와 넘겨받은 파라미터를 사용하여 표현해주었다.{this.state.commentList.map((commentElement, idx) => { return <li key={idx}>{commentElement}</li>; })}
👇
위의 단계까지 실행하고 댓글을 submit하면,댓글 창에 잘 올라오긴하는데 input에 작성해준 값이 초기화되지 않고 계속 그대로 유지가 될 것이다. 해결하려면 어떻게 해야할까?
- 🍒 우리는 input의 value값을 submit할 때 두가지 작업을 하고 싶다
1) 3번addComment 함수와 4번에서 작성해준 것 같이 input value값이 댓글 창에 올라가도록
2) input value값이 초기화되도록- 위의 이 기능은 각각 따로 실행되어야한다.
이를 위해 나는 input의value
라는 attribute를 통해서 input의 value값의 상태를 바꿔주기로했다
1) 🍒 input를 입력하면 입력값을 담고, 댓글 업로드 후에는 비워주기 위해 this.state에 value : ''
라는 초기값을 넣어주었다.(input의 초기 상태는 빈 문자열이기 때문이다)
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를 다시 빈 문자열로⭐
});
};