import React, { useState, useEffect, useRef } from "react";
import axios from "axios";
const CommentForm = (props) => {
const [inputValue, newInputValue] = useState("")
const changeHandler = (e) => {
newInputValue(e.target.value)
}
const submitHandler = (e) => {
e.preventDefault()
props.create(inputValue)
newInputValue("")
e.target.commentInput.focus()
}
return (
<li className="comment-form">
<form onSubmit={submitHandler}>
<h4>댓글 쓰기
<span> ({props.length})</span>
</h4>
<span className="ps_box">
<input
type="text"
onChange={changeHandler}
className='int'
id="commentInput"
value={inputValue}
placeholder="댓글 내용을 입력해주세요"
/>
</span>
<input type="submit" value="등록" className="btn" />
</form>
</li>
)
}
const CommentItem = (props) => {
const [liMode, editMode] = useState(false)
const [content, newContent] = useState(props.content)
const inputRef = useRef()
// console.log(props)
useEffect(() => {
if (liMode) {
inputRef.current.focus();
}
}, [liMode]);
const modifyHandler = (e) => {
editMode(true)
}
const changeHandler = (e) => {
newContent(e.target.value)
}
const keyPressHandler = async (e) => {
if (e.keyCode === 13) {
const updatedData = e.target.value
await props.modify(updatedData, props.id)
editMode(false)
}
else if (e.keyCode === 27) editMode(false)
}
const deleteHandler = () => {
props.destroy(props.id)
}
return (
<ul className="comment-row">
<li className="comment-id">{props.userid}</li>
{
liMode
? <input type="text" value={content} onChange={changeHandler} ref={inputRef} onKeyDown={keyPressHandler} />
: <li className="comment-content" onClick={modifyHandler}>{props.content}</li>
}
<li className="comment-date">{props.date}</li>
<li className="delete-comment" onClick={deleteHandler}>🆇</li>
</ul>
)
}
const CommentList = (props) => {
const renderList = (v, idx) => {
return <CommentItem key={idx} id={v.id} userid={v.userid} content={v.content} date={v.createdAt.split("T")[0]} destroy={props.destroy} modify={props.modify} />
}
return (
<li>
{props.list.map(renderList)}
</li>
)
}
const Comment = () => {
const [list, newList] = useState([])
const getList = async () => {
const response = await axios.get("http://localhost:3000/comments")
newList(response.data)
}
useEffect(()=> {
getList()
}, [])
// 댓글 생성
const create = async (inputValue) => {
const response = await axios.post("http://localhost:3000/comments", {content : inputValue})
newList([response.data, ...list])
}
// 댓글 수정
const modify = async (content, id) => {
// console.log(content, id)
const response = await axios.put(`http://localhost:3000/comments/${id}`, { content })
if (response.data === 1) {
const updatedList = list.filter(v => v.id !== id)
newList(updatedList)
}
}
// 댓글 삭제
const destroy = async (id) => {
const response = await axios.delete(`http://localhost:3000/comments/${id}`)
if (response.data === 1) {
const updatedList = list.filter(v => v.id !== id)
newList(updatedList)
}
}
return (
<ul className="comment">
<CommentForm create={create} length={list.length} />
<CommentList modify={modify} destroy={destroy} list={list} />
</ul>
)
}
export default Comment
(23/02/28 수정)
<Comment />
입니다Comment
컴포넌트가 수정 및 삭제 후의 상태 관리가 가능하도록 설계해야 합니다create
, modify
, destroy
함수를 상위 컴포넌트에 미리 생성하고 props를 통해서 하위 컴포넌트로 전달하기.filter
메서드를 사용했습니다↓ 혹시 몰라서 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;
position: relative;
}
.comment-content input {
position: absolute;
left: 25px;
top: 0;
width: 90%;
height: 100%;
outline: none;
}
.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;
}