폼만 고정적으로 만들어진 상태 추가적인 댓글은 불가능
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>리액트 시간</title>
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root">
</div>
<script type="text/babel">
class ComponentForm extends React.Component{
render(){
return(
<>
<li className="comment-form">
<form>
<h4>댓글쓰기 <span>(3)</span></h4>
<span className="ps_box">
<input type="text" placeholder="댓글내용을 입력해주세요." className="int"/>
</span>
<input type="submit" value="등록" className="btn"/>
</form>
</li>
</>
)
}
}
class ComponentRow extends React.Component{
render(){
return(
<>
<li>
<ul className="comment-row">
<li className="comment-id">algml</li>
<li className="comment-content">안녕하세요.</li>
<li className="comment-content">반갑습니다.</li>
</ul>
</li>
</>
)
}
}
class CommentApp extends React.Component{
render(){
return(
<>
<ComponentRow/>
<ComponentRow/>
<ComponentRow/>
<ComponentForm/>
</>
)
}
}
// javascript + XML = jsx
// xml => 예전에 데이터 주고받던 형식
ReactDOM.render(
<CommentApp/>,
document.querySelector('#root')
)
</script>
</body>
</html>
댓글 삭제 추가까지 가능한 코드
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>리액트 시간</title>
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<link rel="stylesheet" href="./example6.css">
</head>
<body>
<div id="root">
</div>
<script type="text/babel">
/*
JSX = javascript + xml
*/
class CommentForm extends React.Component{
state = {
content:'',
}
handleChange = (e) => {
this.setState({[e.target.name]:e.target.value})
}
handleSubmit = (e) => {
e.preventDefault()
this.props.onCreate(this.state.content)
this.setState({content:''})
}
render(){
return (
<li className="comment-form">
<form onSubmit={this.handleSubmit}>
<h4>댓글쓰기 <span>({this.props.count})</span></h4>
<span className="ps_box">
<input
type="text"
placeholder="댓글내용을 입력해주세요."
className="int"
name="content"
value={this.state.content}
onChange={this.handleChange}
/>
</span>
<input type="submit" value="등록" className="btn" />
</form>
</li>
);
}
}
class CommentList extends React.Component{
state = {
content:'',
key:Infinity,
}
handleClick = (key) => {
this.setState({key:key})
}
handleChange = (e) => {
this.setState({ [e.target.name]:e.target.value })
}
handleEnter = (e) => {
if(e.key === 'Enter'){
let {key,content} = {...this.state}
this.props.onUpdate(key,content)
this.setState({key:Infinity,content:''})
}
}
inputBox = (content) => {
return(
<input
type="text"
className="comment-update-input"
name="content"
defaultValue={content}
onChange={this.handleChange}
onKeyDown={this.handleEnter}
/>
)
}
renderList = () => {
return(
this.props.items.map((item,key)=>{
return(
<li key={key}>
<ul className="comment-row">
<li className="comment-id">{item.userid}</li>
<li className="comment-content">
<span onClick={()=>{ this.handleClick(key) }}>
{key === this.state.key ? this.inputBox(item.content) : item.content}
</span>
<span
className="comment-delete-btn"
onClick={ ()=>{this.props.onDelete(key)} }
>
X
</span>
</li>
<li className="comment-date">{item.date}</li>
</ul>
</li>
)
})
)
}
input = 0
render(){
return (
<>
{this.renderList()}
</>
);
}
}
class CommentLayout extends React.Component{
render(){
return(
<ul className="comment">
{this.props.children}
</ul>
)
}
}
class Comment extends React.Component{ // 모든 댓글기능이 다그려지는 역활
state = {
list:[]
}
getToday = () => {
let date = new Date();
let year = date.getFullYear();
let month = ("0"+(1+date.getMonth())).slice(-2)
let day = ("0" + date.getDate()).slice(-2)
let hour = ("0"+((date.getHours())-12)).slice(-2)
let minute = ("0"+date.getMinutes()).slice(-2)
let second = ("0"+date.getSeconds()).slice(-2)
return `${year}-${month}-${day} ${hour}-${minute}-${second}`;
}
onCreate = (data) => { // 일단 댓글쓸때 사용할 함수를 미리 선언
let item = {userid:'algml0703',content:data,date:this.getToday()}
let {list} = {...this.state} // 내현재 state list를 복사해서 list라는 변수에 넣겠다.
let newList = [...list,{...item}] // 새로운변수를 선언해서 list라는 변수와, item이라는 변수를 넣어서 새로만들겠다.
this.setState({list:newList})
}
onUpdate = (index,content) => {
let {list} = {...this.state}
list[index].content = content
this.setState({list:list})
}
onDelete = (data) => {
//data 변수 1
let {list} = {...this.state}
let newList = list.filter((value,index)=>{
return data !== index
})
this.setState({list:newList})
}
componentDidMount(){ //생명주기
let list = [
{userid:'algml0703',content:'안녕하세요 반갑습니다.',date:'2021-07-01'},
{userid:'algml0703',content:'안녕하세요 처음 뵙겠습니다.',date:'2021-07-01'},
{userid:'algml0703',content:'안녕하세요 제 이름은',date:'2021-07-01'},
]
this.setState({list:list})
}
render(){
return(
<CommentLayout>
<CommentForm
onCreate={this.onCreate}
count={this.state.list.length}
/>
<CommentList
items={this.state.list}
onDelete={this.onDelete}
onUpdate={this.onUpdate}
/>
</CommentLayout>
)
}
}
class App extends React.Component{
render(){
return(
<Comment />
)
}
}
ReactDOM.render(
<App />,
document.querySelector('#root')
)
</script>
</body>
</html>
업데이트까지 구현된 코드
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>리액트 시간</title>
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<link rel="stylesheet" href="./example6.css">
</head>
<body>
<div id="root">
<!--
<ul class="comment">
<li>
<ul class="comment-row">
<li class="comment-id">algml0703</li>
<li class="comment-content">안녕하세요 반갑습니다.</li>
<li class="comment-date">20221-06-28</li>
</ul>
</li>
<li>
<ul class="comment-row">
<li class="comment-id">algml0703</li>
<li class="comment-content">안녕하세요 반갑습니다.</li>
<li class="comment-date">20221-06-28</li>
</ul>
</li>
<li>
<ul class="comment-row">
<li class="comment-id">algml0703</li>
<li class="comment-content">안녕하세요 반갑습니다.</li>
<li class="comment-date">20221-06-28</li>
</ul>
</li>
<li class="comment-form">
<form>
<h4>댓글쓰기 <span>(3)</span></h4>
<span class="ps_box">
<input type="text" placeholder="댓글내용을 입력해주세요." class="int"/>
</span>
<input type="submit" value="등록" class="btn"/>
</form>
</li>
</ul>
-->
</div>
<script type="text/babel">
/*
JSX = javascript + xml
*/
class CommentForm extends React.Component{
state = {
content:'',
}
handleChange = (e) => {
this.setState({[e.target.name]:e.target.value})
}
handleSubmit = (e) => {
e.preventDefault()
this.props.onCreate(this.state.content)
this.setState({content:''})
}
render(){
return (
<li className="comment-form">
<form onSubmit={this.handleSubmit}>
<h4>댓글쓰기 <span>({this.props.count})</span></h4>
<span className="ps_box">
<input
type="text"
placeholder="댓글내용을 입력해주세요."
className="int"
name="content"
value={this.state.content}
onChange={this.handleChange}
/>
</span>
<input type="submit" value="등록" className="btn" />
</form>
</li>
);
}
}
class CommentList extends React.Component{
state = {
content:'',
key:Infinity,
}
handleClick = (key) => {
this.setState({key:key})
}
handleChange = (e) => {
this.setState({ [e.target.name]:e.target.value })
}
handleEnter = (e) => {
if(e.key === 'Enter'){
let {key,content} = {...this.state}
this.props.onUpdate(key,content)
this.setState({key:Infinity,content:''})
}
}
inputBox = (content) => {
return(
<input
type="text"
className="comment-update-input"
name="content"
defaultValue={content}
onChange={this.handleChange}
onKeyDown={this.handleEnter}
/>
)
}
renderList = () => {
return(
this.props.items.map((item,key)=>{
return(
<li key={key}>
<ul className="comment-row">
<li className="comment-id">{item.userid}</li>
<li className="comment-content">
<span onClick={()=>{ this.handleClick(key) }}>
{key === this.state.key ? this.inputBox(item.content) : item.content}
</span>
<span
className="comment-delete-btn"
onClick={ ()=>{this.props.onDelete(key)} }
>
X
</span>
</li>
<li className="comment-date">{item.date}</li>
</ul>
</li>
)
})
)
}
input = 0
render(){
return (
<>
{this.renderList()}
</>
);
}
}
class CommentLayout extends React.Component{
render(){
return(
<ul className="comment">
{this.props.children}
</ul>
)
}
}
class Comment extends React.Component{ // 모든 댓글기능이 다그려지는 역활
state = {
list:[]
}
onCreate = (data) => { // 일단 댓글쓸때 사용할 함수를 미리 선언
let item = {userid:'algml0703',content:data,date:'2021-07-01'}
let {list} = {...this.state} // 내현재 state list를 복사해서 list라는 변수에 넣겠다.
let newList = [...list,{...item}] // 새로운변수를 선언해서 list라는 변수와, item이라는 변수를 넣어서 새로만들겠다.
this.setState({list:newList})
}
onUpdate = (index,content) => {
let {list} = {...this.state}
list[index].content = content
this.setState({list:list})
}
onDelete = (data) => {
//data 변수 1
let {list} = {...this.state}
let newList = list.filter((value,index)=>{
return data !== index
})
this.setState({list:newList})
}
componentDidMount(){ //생명주기
let list = [
{userid:'algml0703',content:'안녕하세요 댓글이에요1',date:'2021-07-01'},
{userid:'algml0703',content:'안녕하세요 댓글이에요2',date:'2021-07-01'},
{userid:'algml0703',content:'안녕하세요 댓글이에요3',date:'2021-07-01'},
]
this.setState({list:list})
}
render(){
return(
<CommentLayout>
<CommentForm
onCreate={this.onCreate}
count={this.state.list.length}
/>
<CommentList
items={this.state.list}
onDelete={this.onDelete}
onUpdate={this.onUpdate}
/>
</CommentLayout>
)
}
}
class App extends React.Component{
render(){
return(
<Comment />
)
}
}
ReactDOM.render(
<App />,
document.querySelector('#root')
)
</script>
</body>
</html>
css
*{margin:0; padding:0;}
body{
font-family: 'Noto Sans KR', sans-serif;
font-weight:300;
}
ul,li{
list-style:none;
}
.comment{
display:flex;
flex-direction: column;
flex-wrap: nowrap;
padding:30px;
width:600px;
margin:0 auto;
}
.comment > li{ margin-top:20px; }
.comment > li:nth-child(1){ margin:0px;}
.comment-row{
display:flex;
justify-content: space-between;
flex-direction: row;
}
.comment-row{
margin-top:20px;
width:100%;
}
.comment-row > li:nth-child(2){
flex-shrink: 0;
flex-grow: 1;
padding-left:25px;
z-index:1;
width:100%;
}
.comment-row > li:nth-child(2){
width:85px;
}
.comment-form > form{
display:flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
}
.comment-form > form > h4{
width:100%;
margin:14px 0 14px 0;
}
.comment-content{
word-break:break-all;
padding-right:25px;
}
.ps_box{
display: block;
position: relative;
width: 80%;
height: 51px;
border: solid 1px #dadada;
padding: 10px 14px 10px 14px;
background: #fff;
box-sizing: border-box;
}
.ps_box > input{
outline:none;
}
.int{
display: block;
position: relative;
width: 100%;
height: 29px;
padding-right: 25px;
line-height: 29px;
border: none;
background: #fff;
font-size: 15px;
box-sizing: border-box;
z-index: 10;
}
.btn{
width:18%;
padding: 18px 0 16px;
text-align: center;
box-sizing: border-box;
text-decoration: none;
border:none;
background:#333;
color:#fff;
font-size:14px;
}
.comment-delete-btn{
display:inline-block;
margin-left:7px;
cursor: pointer;
}
.comment-update-input{
border:none;
border-bottom: 1px solid #333;
font-size:16px;
color:#666;
outline: none;
}