fullstack-react-toy(1) 환경 세팅, 목록뷰 구현하기, 새글쓰기 기능 구현

Jiwontwopunch·2022년 7월 9일
0

독학

목록 보기
95/102
post-thumbnail

환경 세팅

yarn init -y
package.json에 추가 코드 작성

  "private": true,
  "workspaces":[
    "client",
    "server"
  ],
  "scripts": {
    "client":"yarn workspace client start",
    "server":"yarn workspace server start"
  }

client, server 폴더 생성
cd client
yarn init -y
yarn add react react-dom next sass axios
yarn add --dev webpack
client/pages/index.js

// pages 폴더는 next.js에서 기반이 되는 폴더

const Home=()=>(
  <>
  <h1>Simple SNS</h1>
  </>
)

export default Home

client/package.json

  },
  "scripts": {
    "start": "next"
  },

root폴더로 이동해서 yarn run client
localhost:3000 브라우저에서 확인하면

목록뷰 구현하기

client/components/MsgList.js

import MsgItem from "./MsgItem"


/*
const MsgList=()=><ul className="message">{
   [] 배열에 있는 정보를 임시로 mock데이터로 
  [].map(x=><MsgItem {...x}/>)
}</ul>
*/

const UserIds=['roy','jay']
const getRandomUserId=()=>UserIds[Math.round(Math.random())]
const msgs=Array(50).fill(0).map((_,i)=>({
  id:50-i,
  userId: getRandomUserId(),
  timestamp: 1234567890123+50-i*1000*60,
  text: `${50-i} mock text`
}))

const MsgList=()=>(
  <ul className="message">
    {msgs.map(x=>(
      <MsgItem key={x.id} {...x} />
    ))}
  </ul>
)

export default MsgList

client/components/MsgItem.js

const MsgItem=({userId,timestamp,text})=>(
  <li className="message__item">
    <h3>
      {userId}{' '}
      <sub>
        {new Date(timestamp).toLocaleDateString('ko-XR',{
          year:'numeric',
          month: 'numeric',
          day:'numeric',
          hour:'2-digit',
          minute:'2-digit',
          hour12: true
        })}
      </sub>
    </h3>
    {text}
  </li>
)

export default MsgItem

pages/index.js

// pages 폴더는 next.js에서 기반이 되는 폴더
import MsgList from "../components/MsgList"

const Home=()=>(
  <>
  <h1>Simple SNS</h1>
  <MsgList />
  </>
)

export default Home


pages/index.scss → 스타일 작성 (일단 생략)

새글쓰기 기능 구현

pages/_app.js

import './index.scss'

// next가 서버사이드렌더링 하기 위해 필요, 기본 공식처럼 있으니까 그냥 따라하면 된다.
const App=({Component, pageProps})=><Component {...pageProps} />

App.getInitialProps=async({ctx,Component})=>{
  const pageProps=await Component.getInitialProps?.(ctx)
  return {pageProps}
}

export default App

client/next.config.js

const path=require("path")

module.exports={
  sassOption:{
    includePaths:[path.resolve(__dirname,'./pages')],
  },
}

components/MsgInput.js

import { useRef } from 'react'

const MsgInput=({mutate})=>{
  const textRef=useRef(null)
  const onSubmit=e=>{
    e.preventDefault()
    e.stopPropagation()
    const text=textRef.current.value
    textRef.current.value=''
    mutate(text)
  }
  return (
    <form className='message__input' onSubmit={onSubmit}>
      <textarea
        ref={textRef}
        placeholder="내용을 입력하세요."
        />
    </form>
  )
}
export default MsgInput

MsgList.js에 state가 바뀌는걸 반영

import MsgItem from "./MsgItem"
import { useState } from "react"
import MsgInput from "./MsgInput"


/*
const MsgList=()=><ul className="message">{
   [] 배열에 있는 정보를 임시로 mock데이터로 
  [].map(x=><MsgItem {...x}/>)
}</ul>
*/

const UserIds=['roy','jay']
const getRandomUserId=()=>UserIds[Math.round(Math.random())]
const msgs=Array(50).fill(0).map((_,i)=>({
  id:50-i,
  userId: getRandomUserId(),
  timestamp: 1234567890123+(50-i)*1000*60,
  text: `${50-i} mock text`,
}))

const MsgList=()=>{
  const [msgs,setMsgs]=useState(originalMsgs)
  const onCreate=text=>{
    const newMsg={
      id:msgs.length,
      userId: getRandomUserId(),
      timestamp: Date.now(),
      text: `${msgs.length+1} ${text}`
    }
    setMsgs(msgs=>([newMsg,...msgs]))
  }
  return (
  <>
  <MsgInput mutate={onCreate} />
  <ul className="message">
    {msgs.map(x=>(
      <MsgItem key={x.id} {...x} />
    ))}
  </ul>
  </>
)
}

export default MsgList

0개의 댓글