<>, </>원래 사용하던 npm이 아닌 yarn을 사용하여 패키징을 관리하는 것 부터 난관봉착.
body {
margin: 0;
}
#__next {
margin: 10px;
}
h1 {
text-align: center;
margin: 20px 0;
}
.messages {
list-style: none;
padding: 0;
margin: 0;
&__input {
display: flex;
width: 80%;
max-width: 700px;
min-width: 400px;
margin: 0 auto 10px;
> * {
box-sizing: border-box;
}
textarea {
padding: 10px;
flex-grow: 1;
}
button {
margin-left: 5px;
width: 60px;
}
}
&__item {
position: relative;
margin: 10px 0;
padding: 15px 15px 5px;
border-radius: 5px;
border: solid 1px #aaa;
h3 {
font-size: 0.85em;
margin: 0 0 10px;
}
sub {
font-weight: normal;
margin-left: 5px;
vertical-align: baseline;
}
p {
margin: 10px 0;
}
&:hover .messages__buttons {
display: block;
}
.messages__input {
width: 100%;
}
}
&__buttons {
display: none;
position: absolute;
text-align: right;
right: 10px;
bottom: 10px;
}
}
그냥 아무것도 모르겠어서 뭘 모르겠는지도 모르겠는 상태로 시작한 강의
거기서 맞닥뜨린 두 번 째 난관

입력폼에 메시지를 입력해서 잘 나오나 확인해야되는데 류발 자꾸 저 에러메세지때문에 자동 새로고침이 돼서 확인이 안된다.
에러메세지를 열심히 잘 살펴보니

const getRandomUserId = () => UserIds[Math.round(Math.random())];
위 함수에서 Math.random() 함수가 서버와 클라이언트 사이에서 충돌이 일어난 듯 보였음.. 강의창에서는 한 번도 관련된 얘기가 없어서 질문 목록을 살펴보니 어떤 학생 분께서 홀로 해결하신 걸 발견 ... 동지애 뿜뿜쓰...
선생님께서도 '하나의 함수를 서버에서도 한 번, 클라이언트에서도 한 번 실행합니다. 함수 실행 결과가 랜덤이라 매 번 값이 달라지니 자연히 "서버와 클라이언트의 text content가 같지 않다"는 오류가 발생할 수밖에 없습니다.' 라고 답글을 다셨던디 무책임해
뭐 아무튼 Client - 프론트단에서 구현해낸 코드까지만 정리해보자면
import { useState } from 'react'
import MsgItem from './Msgitem'
import MsgInput from './MsgInput'
// const UserIds = ['roy', 'jay']
// const getRandomUserId = () => UserIds[Math.round(Math.random())]
const originalMsgs = Array(50).fill(0).map((_, i) => ({
id: i + 1,
userId : '익명',
timestamp: 1234567890123 + i * 1000 * 60,
text: `${i + 1} mock text`
}))
.reverse()
const MsgList = () => {
const [msgs, setMsgs] = useState(originalMsgs)
const [editingId, setEditingId] = useState(null)
const onCreate = text => {
const newMsg = {
id: msgs.length +1,
userId: '익명',
timestamp: Date.now(),
text: `${msgs.length +1} ${text}`,
}
setMsgs(msgs => ([newMsg, ...msgs]))
}
const onUpdate = (text, id) => {
setMsgs(msgs => {
const targetIndex = msgs.findIndex(msg => msg.id === id)
if (targetIndex < 0) return msgs
const newMsgs = [...msgs]
newMsgs.splice(targetIndex, 1, {...msgs[targetIndex], text})
return newMsgs
})
doneEdit()
}
const doneEdit = () => setEditingId(null)
const onDelete = (id) => {
setMsgs(msgs => {
const targetIndex = msgs.findIndex(msg => msg.id === id)
if (targetIndex < 0) return msgs
const newMsgs = [...msgs]
newMsgs.splice(targetIndex, 1)
return newMsgs
})
}
return (
<>
<MsgInput mutate={onCreate} />
<ul className="messages">
{msgs.map(x => (
<MsgItem
key={x.id}
{...x}
onUpdate={onUpdate}
onDelete={() => onDelete(x.id)}
startEdit={() => setEditingId(x.id)}
isEditing={editingId === x.id}
/>
))}
</ul>
</>
)
}
export default MsgList
import MsgInput from "./MsgInput"
const MsgItem = ({ id, userId, timestamp, text, onUpdate, isEditing, startEdit, onDelete }) => (
<li className="messages__item">
<h3>
{userId}{' '}
<sub>
{new Date(timestamp).toLocaleString('ko-KR', {
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
hour12: true
})}
</sub>
</h3>
{isEditing ? (
<>
<MsgInput mutate={onUpdate} text={text} id={id}/>
</>
) : (
text
)}
<div className="messages_buttons">
<button onClick={startEdit}>수정</button>
<button onClick={onDelete}>삭제</button>
</div>
</li>
)
export default MsgItem
import { useRef } from 'react'
const MsgInput = ({ mutate, text='' ,id = undefined }) => {
const textRef = useRef(null)
const onSubmit = e => {
e.preventDefault()
e.stopPropagation()
const text = textRef.current.value
textRef.current.value = ''
mutate(text, id)
}
return(
<form className="messages__input" onSubmit={onSubmit}>
<textarea ref={textRef} defaultValue={text} placeholder='내용을 입력하세요.'/>
<button type="submit">완료</button>
</form>
)
}
export default MsgInput
결국 서버랑 클라이언트 충돌로 자꾸 프론트로 보이는거 자체가 안돼서 getRandomUserId() 포기함 ㅠ
이렇게 해서 나온 결과 프론트

수정이랑 삭제까지 구현해냄

MsgLists.js
에다가
console.log(JSON.stringify(originalMsgs))

진짜 개빡쳤는데

역시나
그래서 나는 server 폴더 안에 있는 package.jason 파일 안에 "type": "module"을 추가했더니 바로 해결됨 ..ㅎ..
악 짜증나!
