
리액트로 인스타그램의 피드창에서 댓글 업로드 하는 기능을 구현해봤다. 바닐라 자바스크립트에서는 querySelector로
Dom요소를 가지고와서 addeventListener로 동적인 이벤트를 할당해줬다. 리액트에서는 완전히 다르다.
기본적으로 리액트에서는 어떤값이 변할때마다 화면에 영향을 줄 수 있는 값들은 state라는 컨테이너에서 관리해주는게 중요하다!!
변경된 state값이나 동적인 이벤트를 실행하는 함수를 props로 넘겨줘서 작동시킨다.
import React, { Component } from 'react';
import './Main.scss';
import MainRight from './MainRight';
import Feed from './Feed';
class Main extends Component {
constructor() {
super();
this.state = {
id: 0,
input: '',
commentBox: [],
};
}
onInputChange = e => {
this.setState({
input: e.target.value,
});
};
commentUpdate = event => {
const { commentBox, input, id } = this.state;
if (event.key === 'Enter' && input.length > 0) {
const newCommentBox = commentBox.concat({ id: id, content: input });
this.updateComment(newCommentBox, id);
}
};
clickUpdate = () => {
const { commentBox, input, id } = this.state;
if (input.length > 0) {
const newCommentBox = commentBox.concat({ id: id, content: input });
this.updateComment(newCommentBox, id);
}
};
updateComment = (newCommentBox, id) => {
this.setState({
id: id + 1,
commentBox: newCommentBox,
input: '',
});
};
render() {
const { input, commentBox } = this.state;
const { commentUpdate, onInputChange, clickUpdate } = this;
return (
<div className="mainContainer">
<div className="main">
<div className="feeds">
<Feed
input={input}
commentBox={commentBox}
commentUpdate={commentUpdate}
onInputChange={onInputChange}
clickUpdate={clickUpdate}
/>
</div>
<MainRight />
</div>
</div>
);
}
}
export default Main;
Main페이지를 구성하는 최상단 부모 컴포넌트다. state값은 부모에서 자식 컴포넌트로 일방적으로 전달되어야하기때문에
state의 값은 전부 다 Main컴포넌트에서 관리해줘야된다. state에는 댓글의 순서인 id와 댓글의 입력값을 실시간으로 받는
input 그리고 댓글들을 배열로 관리하는 commentBox가 state에 있다. 댓글이 입력되고 업로드되는 컴포넌트는 Feed컴포넌트로
분리해줬다. commentUpdate와 clickUpdate 메소드를 보면 concat이라는걸 사용해서 commentBox를 복사해서 값을 추가해서
새로운 변수에다가 할당을 해주는데 이는 리액트에서 state내부에 있는 객체나 배열의 값을 바꿔야할때 push()같은 원본 배열을
변경시켜서 setState가 할당을 해주면 안된다!! 반드시 복사를 한 후 새로운 배열을 할당을 해줘야된다. 이는 리액트의 성능과 연결된다.
Feed 컴포넌트에 props들을 넘겨주는데 input, commentBoxs는 state에서 관리되는 input, commentBox이고 commentUpdate, onInputChange, clickUpdate는 메인컴포넌트에서 선언된 메소드들을 props로 넘겨준 상태다. 이제 Feed컴포넌트에서 넘겨받은 props를 어떻게 사용하는지 보면...
import React, { Component } from 'react';
import Comments from './Comments';
class Feed extends Component {
render() {
const { input, commentBox, commentUpdate, onInputChange, clickUpdate } =
this.props;
return (
{/* 이상 생략 */}
<ul className="comments">
<Comments comment={commentBox} />
</ul>
<div className="commentBox">
<img src="/images/ChangminJeon/smile.png" alt="smile" />
<input
value={input}
type="text"
className="commentInput"
placeholder="댓글달기..."
onKeyPress={commentUpdate}
onChange={onInputChange}
/>
<div
className={input ? 'onUploadButton' : 'offUploadButton'}
onClick={clickUpdate}
>
게시
</div>
</div>
</div>
</div>
);
}
}
export default Feed;
기능의 핵심인 부분만 코드블럭에 나타냈다. 먼저 render()함수 밑에 구조분해할당으로 props값으로 받은것을 가지고 왔다.
ul태그 사이에 Comments 컴포넌트가 있는데 여기서 댓글들이 담겨있는 commentBox를 comment props로 받는다.
그리고 밑에 input태그는 vaule속성에는 input props를 받고 키가 눌렸을때는 commentUpdate메소드가 실행되는 props
그리고 input값이 변경될때마다 onInputChange메소드가 실행되게 props들이 넘겨졌다.
Comments 컴포넌트에서 props로 받은 comment를 어떻게 화면상에서 구현이되는지 보자.
import React, { Component } from 'react';
class Comments extends Component {
render() {
const { comment } = this.props;
const box = comment.map(comment => {
return (
<li key={comment.id} className="comment">
{comment.content}
</li>
);
});
return <>{box}</>;
}
}
export default Comments;
Comments 컴포넌트에서 props로 받은 comment를 선언을 해주고 이건 Main 컴포넌트 state에 있는 commentBox이다.
이 배열을 map으로 순회하면서 값을 <li>태그를 붙여주면서 값을 부여하고 box라는 변수에 새로운 배열을 할당해준다.
그리고 이 box변수를 return문에다가 넣어주면 화면에 랜더링되면서 구현된다!
이번 프로젝트에서 가장 중요한 사실은 바로 부모 컴포넌트에 있는 state 및 메소드를 어떻게 자식 컴포넌트에 props로 넘겨주고 넘겨받은 props를 어떻게 구현하는지를 알게된 프로젝트였다.
'React' 카테고리의 다른 글
TIL 16 MockData 활용하기 (0) | 2021.11.04 |
---|---|
TIL 15 React LifeCycle (0) | 2021.10.29 |
TIL 14 React 불변성 (0) | 2021.10.28 |
TIL 14 React로 인스타그램 로그인 구현(setState, 삼항연산자) (0) | 2021.10.24 |
TIL 13 JSX, React 기초부터 (0) | 2021.10.18 |