따라하며 배우는 리액트 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.com/braverokmc79/react-button-app
[7]. Next.js와 TypeScript
84. TypeScript Type
강의:
https://www.inflearn.com/course/따라하는-리액트/unit/119930?tab=curriculum

85. Typescript 추가 제공 타입
강의:
https://www.inflearn.com/course/따라하는-리액트/unit/119931?tab=curriculum

86. Type annotation, Type inference
강의:
www.inflearn.com/course/따라하는-리액트/unit/119932?tab=curriculum

87. Type assertion
강의:
www.inflearn.com/course/따라하는-리액트/unit/119933?tab=curriculum

88. getStaticProps를 이용한 포스트 리스트 나열
강의:
www.inflearn.com/course/따라하는-리액트/unit/119934?tab=curriculum

lib/post.ts
import fs from 'fs'
import path from 'path'
import matter from 'gray-matter'
const postsDirectory =path.join(process.cwd(), 'posts');
export  function getSortedPostsData(){
    console.log( " getSortedPostsData  ");
    // posts 파일 이름을 잡아주기
    const fileNames =fs.readdirSync(postsDirectory);
    //['pre-redndering.md' ,  ...]
    const allPostsData =fileNames.map(fileName => {
        const id=fileName.replace(/\.md$/, "");
        const fullPath =path.join(postsDirectory, fileName);
        const fileContents =fs.readFileSync(fullPath, 'utf-8');
        const matterResult =matter(fileContents);
        return{
            id,
            ...(matterResult.data as {data :string; title:string})
        }
    })
    console.log(allPostsData);
    return allPostsData.sort((a, b) =>{
            if(a.date <b.date){
                return 1;
            }else{
                return -1;
            }
    });
}
src/pages/index.tsx
import Head from 'next/head'
import { Inter } from '@next/font/google'
import homeStyles from '@/styles/Home.module.css'
import { GetStaticProps } from 'next'
import {getSortedPostsData} from "../../lib/post";
const inter = Inter({ subsets: ['latin'] })
export default function Home({ allPostsData }: {
  allPostsData: {
    date: string
    title: string
    id: string
  }[]
}) {
  console.log( " postValue 내용: " , allPostsData);
  return (
    <>
      <Head>
        <title>JUNHO CHOI</title>
        <meta name="description" content="Generated by create next app" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <section className={homeStyles.headingMd}>
        <p>[Macaronics Introduction]</p>
      </section>
      <section className={`${homeStyles.headingMd} ${homeStyles.padding1px}`}>
        <h2 className={homeStyles.headingLg}>Blog</h2>
        <ul className={homeStyles.list}>
            {allPostsData.map(({id, title, date})=>
              <li className={homeStyles.listItem} key={id}>
                  <a>{title}</a>
                  <br/>
                  <small className={homeStyles.lightText}>
                    {date}
                  </small>
              </li>
            )}
        </ul>
      </section>
  
    </>
  )
}
export const getStaticProps: GetStaticProps = async () => {
  const allPostsData = getSortedPostsData()
  return {
    props: {
      allPostsData
    }
  }
}
89.포스트 자세히 보기 페이지로 이동(file system 기반의 라우팅)
강의:
www.inflearn.com/course/따라하는-리액트/unit/119935?tab=curriculum

src/pages/posts/[id].tsx
import React from 'react'
export default function Post() {
  return (
    <div>[id]</div>
  )
}
src/pages/index.tsx
~
        <ul className={homeStyles.list}>
            {allPostsData.map(({id, title, date})=>
              <li className={homeStyles.listItem} key={id}>
                 <Link href={`/posts/${id}`}>
                     {title}
                  </Link>
                  <br/>
                  <small className={homeStyles.lightText}>
                    {date}
                  </small>
              </li>
            )}
        </ul>
~
90.포스트 데이터를 가져와서 보여주기(remark)
강의:
www.inflearn.com/course/따라하는-리액트/unit/119936?tab=curriculum

src/pages/posts/[id].tsx
import { getAllPostIds, getPostData } from 'lib/post';
import Head from 'next/head'
import homeStyles from '../../styles/home.module.css'
import { GetStaticProps } from 'next';
import React from 'react'
export default function Post({
  postData
} : { 
  postData:{
    title:string,
    date:string,
    contntHtml :string
  }
}) {
  return (
    <div>
            <Head>
                <title>{postData.title}</title>
            </Head>
            <article>
                <h1 className={homeStyles.headingXl}>{postData.title}</h1>
                <div className={homeStyles.lightText}>
                    {postData.date}
                </div>
                <div dangerouslySetInnerHTML={{ __html: postData.contentHtml }} />
            </article>
        </div>
  )
}
export const getStaticPaths: GetStatiPaths = async ()=>{
   const paths =getAllPostIds();
   console.log( 'paths ' , paths);
    return{
      paths,
      fallback:false
    }
}
// paths  [ { params: { id: 'pre-rendering' } }, { params: { id: 'ssg-ssr' } } ]
// params  { id: 'pre-rendering' }
export const getStaticProps : GetStaticProps = async ({params}) =>{
   console.log('params ' ,  params);
   const postData = await getPostData(params.id as string);
   return{
      props:{
        postData
      }
   }
}
lib/post.ts
import fs from 'fs'
import path from 'path'
import matter from 'gray-matter'
import { remark } from 'remark'
import html from 'remark-html'
const postsDirectory =path.join(process.cwd(), 'posts');
export  function getSortedPostsData(){
   
    // posts 파일 이름을 잡아주기
    const fileNames =fs.readdirSync(postsDirectory);
    //['pre-redndering.md' ,  ...]
    const allPostsData =fileNames.map(fileName => {
        const id=fileName.replace(/\.md$/, "");
        const fullPath =path.join(postsDirectory, fileName);
        const fileContents =fs.readFileSync(fullPath, 'utf-8');
        const matterResult =matter(fileContents);
        return{
            id,
            ...(matterResult.data as {data :string; title:string})
        }
    })
   
    return allPostsData.sort((a, b) =>{
            if(a.date <b.date){
                return 1;
            }else{
                return -1;
            }
    });
}
export function getAllPostIds(){
    const fileNames =fs.readdirSync(postsDirectory);
    return fileNames.map(fileName=>{
        return{
            params:{
                id:fileName.replace(/\.md$/, '')
            }
        }
    })
}
export async function getPostData(id :string){
    const fullPath =path.join(postsDirectory, `${id}.md`);
    const fileContents =fs.readFileSync(fullPath,  'utf8');
    //Use gray-matter to parse the post metadata section
    const matterResult =matter(fileContents);
    //Use remark to convert markdown into HTML string
    const processedContent =await remark()
        .use(html).process(matterResult.content)
    const contentHtml =processedContent.toString();
    return{
        id,
        contentHtml,
        ...(matterResult.data as {date :string;  title:string})
    }
}
91.블로그앱 스타일링
 
강의:
www.inflearn.com/course/따라하는-리액트/unit/119937?tab=curriculum

 
									













 
댓글 ( 4)  
댓글 남기기