따라하며 배우는 리액트 A-Z
[프론트엔드, 웹 개발] 강의입니다.
이 강의를 통해 리액트 기초부터 중급까지 배우게 됩니다. 하나의 강의로 개념도 익히고 실습도 하며, 리액트를 위해 필요한 대부분의 지식을 한번에 습득할 수 있도록 만들었습니다.
✍️
이런 걸
배워요!
리액트
NextJS
타입스크립트
정적 사이트 자동 배포
도커
강의: https://www.inflearn.com/course/%EB%94%B0%EB%9D%BC%ED%95%98%EB%8A%94-%EB%A6%AC%EC%95%A1%ED%8A%B8#
강의 자료 : https://github.com/braverokmc79/DiagramPDF
소스 :
https://github.dev/braverokmc79/react-nextjs13-app
[8]. Nextjs 13
92. Nextjs 13
강의:
https://www.inflearn.com/course/따라하는-리액트/unit/135794?tab=curriculum
디렉토리 생성
react-nextjs13-app
nextjs 설치
 
$ npx create-next-app@latest ./ --typescript √ Would you like to use ESLint with this project? ... No / Yes √ Would you like to use `src/` directory with this project? ... No / Yes √ Would you like to use experimental `app/` directory with this project? ... No / Yes √ What import alias would you like configured? ... @/* Creating a new Next.js app in F:\Study\React\nextjs-app. Using npm. Installing dependencies: - react - react-dom - next - @next/font - typescript - @types/react - @types/node - @types/react-dom - eslint - eslint-config-next

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  swcMinify:true,
  experimental:{appDir:true}
}
module.exports = nextConfig
app/pages.js
import React from 'react'
export default function page() {
  return (
    <div>메인 페이지</div>
  )
}
app/layout.tsx
import Link from "next/link"
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html>
      <head />
      <body>
         <nav>
            <Link  href="/">
                Home
            </Link> 
            <Link  href="/posts/ ">
                Post
            </Link>
         </nav>
         <main>
         {children}
         </main>
       
        
        </body>
    </html>
  )
}
app/head.tsx
export default function Head() {
  return (
    <>
      <title></title>
      <meta content="width=device-width, initial-scale=1" name="viewport" />
      <link rel="icon" href="/favicon.ico" />
    </>
  )
}
app/posts/pages.js
import Link from "next/link";
import CreatePost from "./CreatePost";
async function  getPost(){
  const res =await fetch("http://127.0.0.1:8090/api/collections/posts/records", {cache : "no-store"}) ;
 
  const data =await res.json();
  //console.log("data  getPost : " , data);
  return data?.items  as  any[];
}
const  PostPage =async()=> {
  const posts =await getPost();
  //console.log("posts  : " , posts);
  return (
    <div>
      <h1>Posts</h1>
      {posts?.map((post)=>{
          return <PostItem  key={post.id}  post={post}   />
      })}
       <CreatePost />      
    </div>
  )
}
export default PostPage;
const PostItem = ({post} : any)=>{
  const {id , title, created } = post ||  {};
  return (
    <div>
        <Link href={`/posts/${id}`}>
            <div>
                <h3>
                  {title}
                </h3>
                <p>{created}</p>
            </div>
          </Link>  
      
     </div>
  )
}
app/posts/CreatePost.tsx
'use client';
import { useState } from "react";
import { useRouter } from 'next/navigation';
const CreatePost = () => {
    const [title, setTitle] = useState('');
    const router = useRouter();
    const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
        e.preventDefault();
        await fetch('http://127.0.0.1:8090/api/collections/posts/records', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                title
            })
        })
        setTitle('');
        // Refresh the current route and fetch new data from the server
        router.refresh();
    }
    return (
        <form onSubmit={handleSubmit}>
            <input
                type="text"
                placeholder="Title"
                value={title}
                onChange={(e) => setTitle(e.target.value)}
            />
            <button type="submit">
                Create post
            </button>
        </form>
    )
}
export default CreatePost
app/posts/[id]/page.tsx
async function getPost(postId :string){
    const res =await fetch(`http://127.0.0.1:8090/api/collections/posts/records/${postId}`, {next: {revalidate:10}});
    if(!res.ok){
        //가장 가까이에 있는 error.js actived
        throw new Error('Failed to fetch data');
    }
    const data =res.json();
    return data;
}
const PostDetailPage = async ({params} : any) => {
  const post =await getPost(params.id);
  return (
    <div>
        <h1>posts/{post.id}</h1>
        <div>
            <h3>{post.title}</h3>
            <p>{post.created}</p>
        </div>
    </div>
  )
}
export default PostDetailPage
app/posts/[id]/error.tsx
'use client';
import { useEffect } from 'react';
export default function Error({
    error,
    reset,
}: {
    error: Error;
    reset: () => void;
}) {
    useEffect(() => {
        // Log the error to an error reporting service
        console.error(error);
    }, [error]);
    return (
        <div>
            <p>Something went wrong!</p>
            <button onClick={() => reset()}>Reset error boundary</button>
        </div>
    );
}
 
									













 
댓글 ( 4)  
댓글 남기기