React

 

따라하며 배우는 리액트 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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

about author

PHRASE

Level 60  라이트

장님은 무뉘나 색채의 아름다움을 볼 수가 없다. 이처럼 도(道)를 알지 못하는 자에게는 아무리 훌륭한 말을 들려주어도 아무 소용이 없는 것이다. -장자

댓글 ( 4)

댓글 남기기

작성