[REACT] ReactJS๋กœ ์˜ํ™” ์›น ์„œ๋น„์Šค ๋งŒ๋“ค๊ธฐ

    (((((((((((๊ธฐ์ด์ด์ธ ๊ธ€ ์ฃผ์˜. ํ•œ ๊ฐ•์˜๋ฅผ ํ•œ ํฌ์ŠคํŠธ์— ์ •๋ฆฌํ•จ)))))))))))

     

     

     

     

    ๋‹น์žฅ ๊ธˆ์š”์ผ๋ถ€ํ„ฐ ๋ฆฌ์•กํŠธ๋ฅผ ์จ์•ผํ•œ๋‹ค. 

    ์ง„์งœ .. ํฐ์ผ๋‚ฌ๋‹ค.

     

    ์ด ๊ธ€์€ ๊ฐ•์˜์˜ ๋ชฉ์ฐจ๋ฅผ ๊ทธ๋Œ€๋กœ ๊ฐ€์ ธ์™€์„œ ๊ทธ ์ˆœ์„œ๋Œ€๋กœ ์ •๋ฆฌํ•  ์˜ˆ์ •์ด๋‹ค. ๋ชฉ์ฐจ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. 

     

    ๋Ÿฌ๋‹์ปค๋ธŒ๊ฐ€ ๋†’์€ react์ด๊ธฐ ๋•Œ๋ฌธ์— ์˜คํžˆ๋ ค ๊ธฐ์ดˆ๋ฅผ ํ™•์‹คํžˆ ์ •๋ฆฌํ•ด๋‘์–ด์•ผ ํ•  ๊ฒƒ ๊ฐ™๋‹ค. 

    ๊ทธ๊ฒŒ ๋ฐ”๋กœ ์˜ค๋Š˜์ด ๋˜๊ธธ ๋ฐ”๋ผ๋ฉด์„œ ์‹œ์ž‘ํ•ด๋ณธ๋‹ค. 

    ๋”๋ณด๊ธฐ
    1 [2021 UPDATE] INTRODUCTION
    #1.1 โค๏ธ ๋ฌด๋ฃŒ ๊ฐ•์˜ โค๏ธ
    #1.2 Why React
    #1.3 Requirements
     
    2 [2021 UPDATE] THE BASICS OF REACT
    #2.0 Introduction
    #2.1 Before React
    #2.2 Our First React Element
    #2.3 Events in React
    #2.4 Recap
    #2.5 JSX
    #2.6 JSX part Two
     
    3 [2021 UPDATE] STATE
    #3.0 Understanding State
    #3.1 setState part One
    #3.2 setState part Two
    #3.3 Recap
    #3.4 State Functions
    #3.5 Inputs and State
    #3.6 State Practice part One
    #3.7 State Practice part Two
    #3.8 Recap
    #3.9 Final Practice and Recap
     
    4 [2021 UPDATE] PROPS
    #4.0 Props
    #4.1 Memo
    #4.2 Prop Types
    #4.3 Recap
     
    5 [2021 UPDATE] CREATE REACT APP
    #5.0 Introduction
    #5.1 Tour of CRA
     
    6 [2021 UPDATE] EFFECTS
    #6.0 Introduction
    #6.1 useEffect
    #6.2 Deps
    #6.3 Recap
    #6.4 Cleanup
     
    7 [2021 UPDATE] PRACTICE MOVIE APP
    #7.0 To Do List part One
    #7.1 To Do List part Two
    #7.2 Coin Tracker
    #7.3 Movie App part One
    #7.4 Movie App part Two
    #7.5 React Router
    #7.6 Parameters
    #7.7 Publishing
    #7.8 Conclusions
    #7.9 Styles
    #7.10 Next Steps
     
    8 INTRODUCTION
    #8.0 ๐Ÿšจ Read this First ๐Ÿšจ
    #8.1 Introduction (01:20)
    #8.2 Requirements (04:24)
    #8.2 Theory Requirements (02:17)
    #8.3 Why React (04:44)
     
    9 SETUP
    #9.0 Creating your first React App (05:40)
    #9.1 Creating a Github Repository (02:36)
    #9.2 How does React work? (06:30)
     
    10 JSX & PROPS
    #10.0 Creating your first React Component (06:54)
    #10.1 Reusable Components with JSX + Props (09:12)
    #10.2 Dynamic Component Generation (09:54)
    #10.3 map Recap (06:51)
    #10.4 Protection with PropTypes (08:51)

    11 STATE

    #11.0 Class Components and State (10:11)

    #11.1 All you need to know about State (07:55)

    #11.2 Component Life Cycle (08:07)

    #11.3 Planning the Movie Component (05:02)

     

    12 MAKING THE MOVIE APP
    #12.0 Fetching Movies from API (08:43)
    #12.1 Rendering the Movies (11:01)
    #12.2 Styling the Movies (06:21)
    #12.3 Adding Genres (06:16)
    #12.4 Styles Timelapse (05:30)
    #12.5 Cutting the summary (03:23)
     
    13 CONCLUSIONS
    #13.0 Deploying to Github Pages (07:37)
    #13.1 Are we done? (04:26)
     
    14 ROUTING BONUS
    #14.0 Getting Ready for the Router (04:14)
    #14.1 Building the Router (08:51)
    #14.2 Building the Navigation (05:36)
    #14.3 Sharing Props Between Routes (07:47)
    #14.4 Redirecting (08:53)
     

    1 [2021 UPDATE] INTRODUCTION

    #1.1 โค๏ธ ๋ฌด๋ฃŒ ๊ฐ•์˜ โค๏ธ

    ํŽ˜์ด์Šค๋ถ์€ ์—ฌ์ „ํžˆ react js ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ์—ฌ์ „ํžˆ ์‚ด์•„๋‚จ์•˜๋‹ค. ํ”„๋ก ํŠธ์•ค๋“œ ๊ฐœ๋ฐœ์ž๋กœ์„œ ์ข‹์€ ๋„๊ตฌ๊ฐ€ ๋  ๊ฒƒ! 

     

    #1.2 Why React

    ์™œ react js๋ฅผ ๋ฐฐ์šฐ๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•œ์ง€, ๊ทธ๋ฆฌ๊ณ  ์–ผ๋งˆ๋‚˜ ์•ˆ์ „ํ•œ์ง€

    ์ฒ˜์Œ์—” ๋งค์šฐ ์œ„ํ—˜ํ–ˆ์ง€๋งŒ ์˜ค๋Š˜๋‚ ์—” ์•„์ฃผ ์ข‹์€ ์„ ํƒ. 

    1. ์‹ ๊ธฐ์ˆ ์„ ๋ฐฐ์šธ๋• ๋ˆ„๊ฐ€ ์ด ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•˜๋Š” ์ง€, ์–ผ๋งˆ๋‚˜ ๊ทœ๋ชจ๊ฐ€ ํฐ ์ง€ ๋ด์•ผํ•œ๋‹ค. ์ƒ์œ„ 1๋งŒ๊ฐœ์˜ ์›น ์‚ฌ์ดํŠธ์ค‘ 44.76%๊ฐ€ ๋ฆฌ์•กํŠธ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ๋ณด๋ฉด ๋จ. 

    ์—์–ด๋น„์•ค๋น„, ์ธ์Šคํƒ€๊ทธ๋žจ, ํŽ˜์ด์Šค๋ถ, ๋„ทํ”Œ๋ฆญ์Šค๊ฐ€ ์‚ฌ์šฉ์ค‘

    2.์ด๋Ÿฐ ๊ฑฐ๋Œ€ํ•œ ํšŒ์‚ฌ์—์„œ ์—ฐ๊ตฌํ•˜๋Š” ์‚ฌ๋žŒ์€ ํ”„๋ก ํŠธ์—”๋“œ๋ฅผ ํฌ๊ฒŒ ๋ฐ”๊พธ๊ณ  ์‹ถ์ง€ ์•Š์•„ํ•œ๋‹ค. ์ž์ฃผ ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ ๊ทธ๋Ÿด ์‹œ๊ฐ„์ด ์—†์Œ. 

    ์•ˆ์ •์ ์ธ๊ฒƒ์„ ์›ํ•œ๋‹ค. ์ด๋Ÿฐ ์‚ฌ๋žŒ๋“ค์ด ์ด์šฉํ•˜๋Š” ๊ฒƒ์„ ๋ฐฐ์šฐ๋Š” ๊ฒƒ์€ ์•„์ฃผ ์ข‹์€ ์„ ํƒ์ด ๋  ๊ฒƒ.

    3. ํฐ ์ปค๋ฎค๋‹ˆํ‹ฐ๋ฅผ ๊ฐ–๊ณ  ์žˆ์Œ. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ž‘ ๋งค์šฐ ๋น„์Šทํ•˜๊ธฐ ๋•Œ๋ฌธ. ๋Œ€๋ถ€๋ถ„ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ž‘์—…์ž„. 

    ์ดํ›„ ๋ฆฌ์•กํŠธ ๋„ค์ดํ‹ฐ๋ธŒ์— ์“ธ ์ˆ˜ ์žˆ์Œ.

     

    #1.3 Requirements

    ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ธฐ์ดˆ๊ฐ€ ์žˆ์–ด์•ผํ•จ. ๋ฐ”๋‹๋ผ js ๋กœ ํฌ๋กฌ์•ฑ ๋งŒ๋“ค๊ธฐ ํ•ด์˜ค๋ผ๊ณ  ํ–ˆ์ง€๋งŒ ์ด๋ฏธ ํ•ด๋ดค๊ธฐ๋„ ํ•˜๊ณ .. pass

     

    2 [2021 UPDATE] THE BASICS OF REACT

    #2.0 Introduction
     

    ๋ฆฌ์•กํŠธ๊ฐ€ ํ•ด๊ฒฐํ•˜๋ ค๊ณ  ํ•˜๋Š” ๋ฌธ์ œ๋Š”?

    REACT JS๋Š” UI๋ฅผ interactive ํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์คŒ.

    ๋ฐ”๋‹๋ผjs์™€ react ์ฝ”๋“œ๋ฅผ ๋น„๊ต

     
    #2.1 Before React
     
    ์ผ๋ฐ˜ ๋ฐ”๋‹๋ผjs

     

    1. html ๋งŒ๋“ค๊ธฐ

    2. javascript ๊ฐ€์ ธ์˜ค๊ธฐ

    3. event ๊ฐ์ง€

    4. ๋ฐ์ดํ„ฐ ์—…๋ฐ์ดํŠธ

    5. html์—…๋ฐ์ดํŠธ

     

    ์ด๋Œ€๋กœ ์ž‘์—…ํ•˜๋‹ค๊ฐ„ ์•„์ฃผ ํ˜ผ๋ž€์Šค๋Ÿฌ์›Œ์งˆ ์ˆ˜ ์žˆ์Œ 

     

    ๋” ์ข‹์€ ๋ฐฉ๋ฒ• : REACT

    reactdhk react-dom ์Šคํฌ๋ฆฝํŠธ ์ถ”๊ฐ€ ๋จผ์ € ํ•˜์ž. 

    <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
    <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
    ์ถ”๊ฐ€ํ•˜๊ณ  ๋‚˜๋ฉด ์ฝ˜์†”์— ๋ฆฌ์•กํŠธ ๋œจ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
    #2.2 Our First React Element
    React js์˜ ๊ทœ์น™์ค‘ ํ•˜๋‚˜๋Š” html ์„ ์ด ํŽ˜์ด์ง€์— ์ง์ ‘ ์ž‘์„ฑํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.
    ๋Œ€์‹  ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์™€ ๋ฆฌ์•กํŠธ js๋ฅผ ํ†ตํ•ด element๋ฅผ ์ƒ์„ฑํ•  ๊ฒƒ์ด๋‹ค. 
     
     
    ๋จผ์ €, react js๋กœ element๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์–ด๋ ค์šด ๋ฐฉ๋ฒ• ์†Œ๊ฐœํ•ด์ค„๊ฑฐ์•ผ
    ์ด๊ฒƒ์€ ๊ฐœ๋ฐœ์ž๋“ค์ด ์“ฐ๋Š” ๋ฐฉ์‹์ด ์•„๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž๋“ค์€ ๊ฒŒ์œผ๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ํˆด์„ ์‚ฌ์šฉํ•œ๋‹ค...
    react js์˜ ๋ณธ์งˆ์„ ๋ฐฐ์šฐ๊ธฐ ์œ„ํ•ด์„œ๋Š” ํ•„์š”ํ•œ ๋‹จ๊ณ„! 
     
    ์Šคํฌ๋ฆฝํŠธ์— import๋œ ๋‘ ๋งํฌ์ค‘ ์ฒซ๋ฒˆ์งธ ๋งํฌ์ธ react js๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด interactiveํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ค์–ด์ฃผ๋Š” library (=ui ๊ทธ๋ฆผ, ์—”์ง„!)์ด๊ณ ,
    react-dom์€ library ํ˜น์€ package์ด๋ฉฐ ๋ชจ๋“  react element๋“ค์„ html body์— ๋‘˜ ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค€๋‹ค.
     
    <!DOCTYPE html>
    <html>
        <body>
            <div id="root"></div>
        </body>
        <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
        <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
        <script>
            const root = document.getElementById("root");
            const span = React.createElement("span", [content]);
            ReactDOM.render(span, root)
        </script>
    </html>

     

     
    render์˜ ์˜๋ฏธ๋Š” span(๋งŒ๋“ค์–ด์ง„ react element)๋ฅผ html๋กœ ๋งŒ๋“ค์–ด ๋ฐฐ์น˜ํ•œ๋‹ค๋Š” ๋œป, ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ์ด๋‹ค. 
     
    render์˜ ๋‘๋ฒˆ์งธ ํŒŒ๋ผ๋ฉ”ํ„ฐ๋Š” span์„ ์–ด๋””์— ๋‘˜ ๊ฒƒ์ธ์ง€๋ฅผ ์ ๋Š”๋‹ค. ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ํ•˜๋Š” ๋ฐฉ์‹์€ id๊ฐ€ root์ธ div๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด๋‹ค. 
    reactdom์—๊ฒŒ span์„ root์— ๋‘๋ผ๋Š” ๋œป 
     
     
     
     
     
    ๋‘๋ฒˆ์งธ argument์—” property๋ฅผ, ์„ธ๋ฒˆ์งธ์—” content๋ฅผ ๋„ฃ์—ˆ๋‹ค. 
     
     
    ์šฐ๋ฆฌ๋Š” span์„ ๋„ฃ๊ณ  ์‹ถ์œผ๋ฉด ๊ทธ๋ƒฅ html์— ์“ฐ๋ฉด ๋œ๋‹ค. 
    ์ด๋ฒˆ ๊ฐ•์˜์˜ ์š”์ ์€ ์ง€๋ฃจํ•œ ์˜ˆ์ œ๋ฅผ ์ฝ”๋”ฉํ•ด๋ด„์œผ๋กœ์จ React JS๋Š” ์šฐ๋ฆฌ๊ฐ€ ํ•ด์™”๋˜ ๋ฐฉ์‹์„ ๊ฑฐ๊พธ๋กœ ํ•˜๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์„ค๋ช…ํ•œ๊ฑฐ์•ผ.
    ๋ฐ”๋‹๋ผ js์—์„œ๋Š” html์„ ๊ทธ๋ƒฅ ๋จผ์ € ๋งŒ๋“ค๊ณ  ๊ทธ๊ฑธ js๋กœ ๊ฐ€์ ธ์™€์„œ html์„ ์ˆ˜์ •ํ•˜๋Š” ์‹์ด์—ˆ๋‹ค๋ฉด
    reactjs๋Š” ๋ชจ๋“  ๊ฒƒ์ด js๋กœ ์‹œ์ž‘ํ•ด ๊ทธ ๋‹ค์Œ์— html์ด ๋˜๋Š” ๊ฒƒ์ด๋‹ค. ์ด๊ฒƒ์ด ๋ฆฌ์•กํŠธ js์˜ ํŒŒ์›Œ์ด๋‹ค. 
    js์™€ react js๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ element๋ฅผ ์ƒ์„ฑํ•  ๋•Œ์—๋Š” react js๊ฐ€ element๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์žˆ๋‹ค. ์ด๋ง์€ reactjs๋Š” ์—…๋ฐ์ดํŠธ๊ฐ€ ํ•„์š”ํ•œ element๋ฅผ ์—…๋ฐ์ดํŠธํ•  ๊ฒƒ์ด๋ผ๋Š” ๋ง์ด๋‹ค. reactjs๊ฐ€ ๊ฒฐ๊ณผ๋ฌผ์ธ html์„ ์ปจํŠธ๋กค ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ์ด๊ฒƒ์ด ํ•ต์‹ฌ! 
     
     
    #2.3 Events in React
     
    ์ด๋ฒคํŠธ๋ฅผ ์ถ”๊ฐ€ํ• ๋•Œ ๊ธฐ์กด์ฒ˜๋Ÿผ clickHandler์ด๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด addEventListener๋ฅผ ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.
    element๋ฅผ ๋งŒ๋“ค๋•Œ on+Event: ๋ฅผ ๋งŒ๋“ค์–ด ๋ฐ”๋กœ ๋„ฃ์„ ์ˆ˜ ์žˆ๋‹ค
    ์ด๊ฑธ ๊ณต๋ถ€ํ•˜๊ณ  ์žˆ์ž๋‹ˆ ํ”Œ๋Ÿฌํ„ฐ๊ฐ€ ๊ทธ๋ฆฝ๋‹ค..
     
    const root = document.getElementById("root");
    const span = React.createElement(
        "h3", {
        id: "prettyspan", 
        style: {color: "blue"},
        onMouseEnter: () => console.log("mouse enter!")
    	}, "Hello I'm a span");
    const btn = React.createElement(
        "button", {
        onClick: () => console.log("i'm clicked")
    }, "Click me");
    const container = React.createElement("div", null, [span, btn]);
    ReactDOM.render(container, root)
     
     
    #2.4 Recap
    ๋ณต์Šตํ•˜๋Š” ์‹œ๊ฐ„! ์‚ฌ์‹ค ์ง€๊ธˆ๋„ ์œ„์—๊ฑฐ ๋‹ค์‹œ ์ฝ์œผ๋ฉด์„œ ์•Œ์•„์„œ ๋ณต์Šตํ•˜๊ณ  ์žˆ๋Š”๋ฐ ๋ณต์Šต์„ ์œ„ํ•œ ๊ฐ•์˜๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“ค์–ด์ฃผ์‹œ๋‹ค๋‹ˆ ๊ฐ์‚ฌํ• ๋”ฐ๋ฆ„ ...! 
     
    1. react js์™€ react dom ์„ importํ–ˆ๋‹ค. ๊ฐ๊ฐ์˜ ๊ธฐ๋Šฅ์€ ์œ„์—..
    2. body์— ์žˆ๋Š” div์ƒ์„ฑ 
    3. root div๋ฅผ ๊ฐ€์ ธ์˜จ ํ›„์— reactDOM.render์„ ํ•จ
     
     createElemet์˜ ๋‘๋ฒˆ์งธ argument์ธ props์—์„œ event๋ฅผ ๋„ฃ์„ ์ˆ˜๋„ ์žˆ๊ณ  id๋ฅผ ๋„ฃ์„ ์ˆ˜๋„์žˆ๊ณ  ..
    reactjs๋Š” ์Šค๋งˆํŠธํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์–ด๋–ค ๊ฒƒ์€ html๋กœ ๊ฐ€์•ผํ•˜๋Š”๋ฐ, ์ด๋ฒคํŠธ๋Š” ์•ˆ๊ฐ„๋‹ค. 
    ์•ž์œผ๋กœ react ๊ฐœ๋ฐœ์ž๋กœ์„œ, createElemet๋ฅผ ์“ธ์ผ์€ ์—†์„ ๊ฒƒ์ด๋‹ค. 
    ํ•˜์ง€๋งŒ ์ด๊ฑด ํ•ต์‹ฌ.! ์–ด๋ ค์šด ๋ฐฉ์‹์ธ๋ฐ๋„ ์ดํ•ด ์™„
     
    ๋ฐ์ดํ„ฐ๋ฅผ ์—…๋ฐ์ดํŠธ ํ•˜๋Š” ๋ฒ•์„ ๊ฐ•์˜์—์„œ ๋‹ค๋ฃจ์ง„ ์•Š์•˜์ง€๋งŒ, ์™ ์ง€ flutter์ฒ˜๋Ÿผ ()=>{ ์—ฌ๊ธฐ ์•ˆ์— ์ฝ”๋“œ๋ฅผ ๋„ฃ์œผ๋ฉด ์—…๋ฐ์ดํŠธ๊ฐ€ ๋  ๊ฒƒ ๊ฐ™์•„์„œ }
    ํ•ด๋ดค๋Š”๋ฐ ๋œ๋‹ค.! 
     
    ๋‹ค์Œ ๊ฐ•์˜์—์„œ๋Š” React element๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋” ์‰ฌ์šด ๋ฐฉ๋ฒ•์„ ๋ฐฐ์›Œ๋ณผ ๊ฒƒ์ด๋‹ค! 
     
    ๊ธฐ๋Œ€๋œ๋‹ค.  
     
     
    #2.5 JSX
    const span = React.createElement(
        "h3", {
        id: "prettyspan", 
        style: {color: "blue"},
        onMouseEnter: () => {
    
            count++;
            console.log("mouse enter! ");
            console.log(count);
        }
    }, "Hello I'm a span");
    const btn = React.createElement(
        "button", {
        onClick: () => console.log("i'm clicked")
    }, "Click me");
     
    ๊ธฐ์กด ๋ฐฉ์‹์—์„œ ์ด๋ถ€๋ถ„์„ ๋ฐ”๊ฟ”๋ณผ ๊ฒƒ์ด๋‹ค! 
    ๊ทธ ํŽธ๋ฆฌํ•œ ๋…€์„์€ jsx๋ผ๋Š” ๊ฒƒ์ด๋‹ค. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ํ™•์žฅํ•œ ๊ฒƒ. 
    ์ƒ๊ธด๊ฒŒ html์ด๋ž‘ ๋น„์Šทํ•ด์„œ jsx๋กœ react ์š”์†Œ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒŒ ๊ฐœ๋ฐœ์ž๋“ค ์ž…์žฅ์—์„œ๋Š” ๊ต‰์žฅํžˆ ํŽธํ•จ. 
     
         const Title = (
            <h3 id="title" onMouseEnter={() => console.log("mouse enter!")}>
            "Hello I'm a span"
            </h3>
        );
     
    ํ•˜.. ์ด๊ฒŒ ๋์ด๋‹ค. ๋„ˆ๋ฌด ๊ฐ„๋‹จํ•˜๊ณ  ๊ฐœ๋ฉ‹์ง€๋‹ค. ์ฐธ html์ด๋ž‘ ๋น„์Šทํ•˜๋ฉด์„œ๋„ flutter๊ฐ€ ์ž๊พธ ์ƒ๊ฐ๋‚˜๋Š” ๋ฌธ๋ฒ•์ด๋‹ค. 
     
    h3ํƒœ๊ทธ๋ฅผ ์—ด๊ณ  ๋‹ซ์œผ๋ฉด ๋˜๊ณ , property๋“ค์€ ๋งˆ์น˜ html ํƒœ๊ทธ์˜ ์†์„ฑ์ฒ˜๋Ÿผ ์ ์œผ๋ฉด ๋œ๋‹ค. 
     
    const Button = (
        <button 
            style={{
                backgroundColor: "tomato"
            }}
            onClick={() => console.log("i'm clicked")}
        >
            click me!
        </button>
    );

    button element๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋งŒ๋“ค์–ด์ฃผ์—ˆ๋‹ค. 

    ์ด๋Œ€๋กœ live server๋ฅผ ๋Œ๋ฆฌ๋ฉด ์—๋Ÿฌ๊ฐ€ ๋œจ๋Š”๋ฐ,

     
    ์šฐ๋ฆฐ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ jsx๋ฅผ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก 
     
    babel๋กœ ์™€์„œ ์šฐ๋ฆฌ์˜ jsx ์ฝ”๋“œ๋ฅผ ๋„ฃ์–ด์ฃผ๋ฉด, ์šฐ๋ฆฌ๊ฐ€ ์ด๋ฏธ ์ ์–ด๋ดค๋˜ ์ฝ”๋“œ๊ฐ€ ๋‚˜์˜จ๋‹ค.

    https://babeljs.io/docs/en/babel-standalone

    ์šฐ๋ฆฌ๋Š” ์ง€๊ธˆ ๋ฐฐ์šฐ๊ณ  ์žˆ์–ด์„œ ์ด ๋ฐฉ์‹์œผ๋กœ ์ง„ํ–‰ํ•˜๋Š” ๊ฑฐ์ง€, ํ˜ผ์žํ•  ๋•Œ๋Š” ์ ˆ๋Œ€ ์ด๋ ‡๊ฒŒ ํ•  ์ผ ์—†์„๊ฒƒ ๋Š๋ฆฌ๊ธฐ๋•Œ๋ฌธ. ๋” ๋‚˜์€ ๋ฐฉ์‹์ด ์žˆ์Œ

     

    babel์„ importํ•ด์ฃผ๊ณ  script ์•ˆ์— type์„ ์ง€์ •ํ•ด์ฃผ๋ฉด ์ด๋ ‡๊ฒŒ ์ž˜ ๋œจ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.  

     
    #2.6 JSX part Two
     
    ์˜คํ‚ค.. ์ด์ œ ํ•ด์ค„๊ฑฐ๋Š” ์œ„์˜ ์ฝ”๋“œ๋ฅผ ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ์ ์–ด๋ณผ๊ฑฐ์ž„ 
    ์™œ๋ƒ๋ฉด ๋‚˜๋Š” rendering์„ ํ•˜๊ณ ์‹ถ์ง€ ์•Š์Œ.
     
    container๋„ createElement๋ฅผ ์—†์• ๋ฒ„๋ฆฌ๊ธฐ ์œ„ํ•ด ์œ„์™€ ๊ฐ™์ด jsx ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•ด content์— Title Button ์ด๋ผ๊ณ  ์ ์œผ๋ฉด ๊ทธ๋ƒฅ ํ…์ŠคํŠธ๊ฐ€ ๋‚˜์™€๋ฒ„๋ฆฐ๋‹ค.. ๊ทธ๋ž˜์„œ ํ•ด์•ผํ•˜๋Š” ๊ฒƒ์€ Title๊ณผ Button์„ ํ•จ์ˆ˜๋กœ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด๋‹ค. 
     
    function Title() {
        return(
        <h3 id="title" onMouseEnter={() => console.log("mouse enter!")}>
        "Hello I'm a span"
        </h3>
        );
    };
    
    const Button = ()=> (
        <button 
            style={{
                backgroundColor: "tomato"
            }}
            onClick={() => console.log("i'm clicked")}
        >
            click me!
        </button>
    );
     
    ๋‘๊ฐœ๊ฐ€ ์•„์˜ˆ ๋˜‘๊ฐ™์Œ.
    arrow funtion์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์€ ์œ„์™€๊ฐ™์ด returnํ•˜์—ฌ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒƒ๊ณผ ๊ฐ™๋‹ค. 
     
    ์ด์ œ container์— ๋„ฃ๊ธฐ ์œ„ํ•ด์„œ๋Š” 
    const Container = (
        <div>
            <Title />
            <Button />
        </div>
    );
     
    ์ด๋ ‡๊ฒŒ ํƒœ๊ทธ๋กœ ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค. ์„ธ์ƒ์— ์ด๋ ‡๊ฒŒ ์‰ฌ์šธ์ˆ˜๊ฐ€! 
    ์šฐ๋ฆฐ ์ง€๊ธˆ ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ๋“ค์ด ํ•ฉ์ณ์ง„ ๊ตฌ์„ฑ์„ ๋งŒ๋“  ๊ฒƒ์ด๋‹ค. 
    divํƒœ๊ทธ๋ฅผ ๋ Œ๋”๋ง ํ•˜๊ณ ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ•˜๋‚˜ ์žˆ๋Š”๋ฐ, title๊ณผ button์— ๊ด€๋ จ๋œ ์ฝ”๋“œ๋ฅผ ํฌํ•จ์‹œํ‚ค๊ณ  ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.
    ์ปดํฌ๋„ŒํŠธ๋Š” ์ „๋ถ€ ๋Œ€๋ฌธ์ž๋กœ ์‹œ์ž‘ํ•ด์•ผํ•œ๋‹ค (html๊ณผ์˜ ํ˜ผ๋ž€ ๋ฐฉ์ง€)
     
    ํ—ค๋” ๊ฐ€๋ฉด ๋ฐ”๋€ ์ฝ”๋“œ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
     
     
    3 [2021 UPDATE] STATE
    #3.0 Understanding State
     
    <script type="text/babel">
        const root = document.getElementById("root");
        let counter = 0;
        function countUp(){
            counter = counter+1;
        }
        const Container = () => (
            <div> 
                <h3>Total clicks: {counter}</h3>
                <button onClick={countUp}> click me!</button>
            </div>
        );
        ReactDOM.render(<Container />, root)
    </script>
     
     
    ์ด ์ฝ”๋“œ์—์„œ ์‹คํ–‰์„ ์‹œ์ผœ๋ณด๋ฉด
    counter์€ ์ž˜ ์˜ฌ๋ผ๊ฐ€์ง€๋งŒ ui๊ฐ€ ๋ฐ”๋€Œ์ง€ ์•Š๊ณ  ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๊ฒƒ์€ Container์„ ํ•œ๋ฒˆ๋งŒ ๋ Œ๋”๋ง ํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

    ์šฐ๋ฆฌ๊ฐ€ countUp ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋ ๋•Œ๋งˆ๋‹ค render์„ ๋‹ค์‹œ ์‹คํ–‰ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค. 

    <script type="text/babel">
        const root = document.getElementById("root");
        let counter = 0;
        function countUp(){
            counter = counter+1;
            render()
        }
        function render(){
            ReactDOM.render(<Container />, root)
        }
        const Container = () => (
            <div> 
                <h3>Total clicks: {counter}</h3>
                <button onClick={countUp}> click me!</button>
            </div>
        );
        render();
    </script>

     ์ด๋ ‡๊ฒŒ renderํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด์ฃผ๋ฉด ๋งค๋ฒˆ ui๊ฐ€ ๋ณ€๊ฒฝ๋œ๋‹ค. 

    ํ•˜์ง€๋งŒ ์ด๊ฑด best๊ฐ€ ์•„๋‹ˆ๋‹ค.

     

     

    ๊ทธ ์ „์—!&nbsp; vanilla.js์™€ ๋‹ค๋ฅด๊ฒŒ ๋ฆฌ์•กํŠธ๋Š” ์—…๋ฐ์ดํŠธ ๋ ๋•Œ ๋ฐ”๋€๋ถ€๋ถ„๋งŒ ์—…๋ฐ์ดํŠธ๋ฅผ ํ•ด์ฃผ๊ณ  ์žˆ๋‹ค๋Š” ์  ํ™•์ธํ•˜๊ณ  ๊ฐ€๊ธฐ~ ๋‹ค๋ฅธ ๋ถ€๋ถ„๋งŒ ํŒŒ์•…ํ•˜๋Š” ReactJS
     
     
    #3.1 setState part One
    ์•ž์„œ ์‚ดํŽด๋ณธ ๋ฐฉ๋ฒ•์€ ์—…๋ฐ์ดํŠธ๊ฐ€ ํ•„์š”ํ• ๋•Œ๋งˆ๋‹ค render() ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰์‹œ์ผœ์ฃผ์–ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํšจ์œจ์ ์ด์ง€ ๋ชปํ•˜๋‹ค.
    ์šฐ๋ฆฌ๋Š” counter๊ฐ€ 0์ผ๋•Œ ์ตœ์ดˆ์˜ render์„ ์‹œํ‚ค๊ณ  ๊ทธ ์ดํ›„์—” ํ•˜๋‚˜์”ฉ + ๋ ๋•Œ๋งˆ๋‹ค ๋ Œ๋”๋ง์ด ๋œ๋‹ค.
     
    <script type="text/babel">
        const root = document.getElementById("root");
        function Container (){
            return (
                <div> 
                    <h3>Total clicks: 0</h3>
                    <button> click me!</button>
                </div>
            );
        }
        ReactDOM.render(<Container />, root)
    </script>
     
    ๋‹ค์‹œ ์ด ์ฝ”๋“œ๋กœ ๋Œ์•„์™€์„œ..! 
     
    const [counter, modifier] = React.useState(0);
     
    counter์™€ modifier์— ๊ธธ์ด๊ฐ€ 2์ธ ๋ฐฐ์—ด์˜ ์š”์†Œ๋“ค์„ ํ•˜๋‚˜์”ฉ ๋„ฃ์–ด์ฃผ๋Š” ์ฝ”๋“œ. 
    useState๋Š” ๋””ํดํŠธ๊ฐ’์ด 0์ด๋ผ๋Š” ๋œป  (counter ์— 0์ด ๋“ค์–ด๊ฐ)
     
     
    #3.2 setState part Two
    <script type="text/babel">
        const root = document.getElementById("root");
        function App (){
            const [counter, setCounter] = React.useState(0);
            return (
                <div> 
                    <h3>Total clicks: {counter}</h3>
                    <button onClick={()=>{setCounter(counter+1)}}> click me!</button>
                </div>
            );
        }
        ReactDOM.render(<App />, root)
    </script>
     
     
    ๊ฐ•์˜์—์„œ๋Š” onClick์ด๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ์„ ์–ธํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š”๋ฐ ๋‚˜๋Š” ๊ทธ๋ƒฅ ๋ฐ”๋กœ ๋ฒ„ํŠผ์•ˆ์— ํ•จ์ˆ˜ ๋„ฃ์–ด๋ฒ„๋ ธ๋‹ค.
    ์ฝ”๋“œ๊ฐ€ ์ •๋ง ๊ฐ„๋‹จํ•˜๊ณ  ์•„๋ฆ„๋‹ต๋‹ค ....โœจ
     
     
    #3.3 Recap
    #3.4 State Functions
     
    ์œ„์™€ ๊ฐ™์€ ์ฝ”๋“œ๋กœ counter์„ ์ปจํŠธ๋กค ํ•˜๊ฒŒ๋˜๋ฉด 
    ์ด์ „ ๋‹จ๊ณ„์˜ state๋ฅผ ์ด์šฉํ•ด์„œ ํ˜„์žฌ state๋ฅผ ๋ฐ”๊พธ๋ ค ํ–ˆ์ง€๋งŒ, ๊ฒฐ๊ณผ๊ฐ€ ์˜ˆ์ƒ๊ณผ ๋‹ค๋ฅด๊ฒŒ ๋‚˜์˜ฌ ์ˆ˜ ์žˆ์Œ
     
    setCounter(counter+1);
    setCounter((current)=>current+1);
     
    ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํ˜„์žฌ ๊ฐ’์„ ๊ธฐ์ค€์œผ๋กœ ๋ฐ”๋€Œ๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ์Œ.
     
     
    #3.5 Inputs and State
    jsx์—์„œ ์•Œ์•„์•ผ ๊ธฐ์–ตํ•ด์•ผํ•  ๊ฒƒ. class ๋Œ€์‹  className, for ๋Œ€์‹  htmlFor์„ ์‚ฌ์šฉํ•ด์•ผํ•จ. 
     
    <script type="text/babel">
        const root = document.getElementById("root");
    
        function App (){
            const [minutes, setMinutes] = React.useState();
            const onChange = (event) => {
                setMinutes(event.target.value);
            }
            return (
                <div> 
                    <label for="minutes">Minutes</label>
                    <input value={minutes} id="minutes" placeholder="Minutes" type="number" onChange={onChange}/>
                    <h4>You want to convert {minutes}</h4>
                    <label>Hours</label>
                    <input placeholder="Hours" type="number"/>
                </div>
            );  
        }
        ReactDOM.render(<App />, root)
    </script>
     
    input๊ฐ’์„ h4์— ๋„ฃ์–ด์ฃผ๋ ค๋ฉด event๋ฅผ ์ด์šฉํ•ด์„œ event.target.value๋ฅผ setMinutes๋ฅผ ์ด์šฉํ•ด์„œ ํ•จ์ˆ˜ ์•ˆ์— ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค.
     
    ๊ทธ๋Ÿฌ๋ฉด ์ด๋ ‡๊ฒŒ ์ˆซ์ž๋ฅผ ์ž…๋ ฅํ• ๋•Œ๋งˆ๋‹ค ์•„๋ž˜์˜ minutes ๊ฐ’์ด ๋ฐ”๋กœ ๋ฐ”๋€œ์Šจ

    ๊ทผ๋ฐ ์—ฌ๊ธฐ์„œ onChange property๋ฅผ ์ง€์›Œ์ฃผ๋ฉด ์•„๋ฌด๋ฆฌ ์ž…๋ ฅํ•˜๋ ค ํ•ด๋„ ๋””ํดํŠธ๊ฐ’์œผ๋กœ ๊ทธ๋Œ€๋กœ ๊ณ ์ •๋จ. ๊ทธ๋ž˜์„œ value์™€ onchange ๋‘˜๋‹ค ํ•„์š”

    #3.6 State Practice part One

    <script type="text/babel">
        const root = document.getElementById("root");
    
        function App (){
            const [minutes, setMinutes] = React.useState();
            const onChange = (event) => {
                setMinutes(event.target.value);
            }
            return (
                <div> 
                    <h1>Super Converter</h1>
                    <label for="minutes">Minutes</label>
                    <input value={minutes} id="minutes" placeholder="Minutes" type="number" onChange={onChange}/>
                    <label for="hours">Hours</label>
                    <input value={minutes/60} placeholder="Hours" type="number" disabled/>
                    <button onClick={()=>{setMinutes(0)}}>reset</button>
                </div>
    
            );  
        }
        ReactDOM.render(<App />, root)
    </script>

    minute์„ hour๋กœ ๋ณ€ํ™˜

     
    #3.7 State Practice part Two
     
    <script type="text/babel">
        const root = document.getElementById("root");
        function App (){
            const [minutes, setMinutes] = React.useState(0);
            const [hours, setHours] = React.useState(0);
            const [flipped, setFlipped] = React.useState(false);
            const onChange = (event) => {
                if(!flipped) {
                    setMinutes(event.target.value);
                    setHours(event.target.value/60);
                }
                else {
                    setHours(event.target.value);
                    setMinutes(event.target.value*60);
                }
            };
            const reset = () => {
                setMinutes(0);
                setHours(0);
            };
            const onFlip = () => {
                setFlipped((current)=> !current);
                reset();
            };
            return (
                <div> 
                    <h1>Super Converter</h1>
                    <label for="minutes">Minutes</label>
                    <input value={minutes} id="minutes" placeholder="Minutes" type="number" onChange={onChange} disabled ={flipped}/>
                    <label for="hours">Hours</label>
                    <input value={hours} id="hours" placeholder="Hours" type="number"  onChange={onChange} disabled ={!flipped} />
                    <button onClick={reset}>reset</button>
                    <button onClick={onFlip}>flip</button>
                </div>
    
            );  
        }
        ReactDOM.render(<App />, root)
    </script>
     
    flip๊ธฐ๋Šฅ๊ณผ reset๊ธฐ๋Šฅ๊นŒ์ง€ ์™„์„ฑํ•œ ์ „์ฒด์ฝ”๋“œ
    ๊ฐ•์˜์—์„œ๋Š” amout๋กœ minutes๊ณผ hours๋ฅผ ํ•ฉ์ณ์„œ ์‚ฌ์šฉํ–ˆ์ง€๋งŒ ๋‚œ ์กฐ๊ธˆ๋” ์ง๊ด€์ ์ธ๊ฒŒ ์ข‹์•„์„œ ์ด๋ ‡๊ฒŒ ํ–ˆ๋‹ค.
    ๊ฐ•์˜์—์„  flip์„ ๊ธฐ์ค€์œผ๋กœ value๋ฅผ if ์จ์„œ ๊ณ„์‚ฐํ•จ
     
     
    #3.8 Recap
     

    ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ฒ„ํŠผ ๋” user-friendly 

    <button onClick={onFlip}>{flipped? "๋ถ„->์‹œ๋กœ ๋ฐ”๊พธ๊ธฐ" : "์‹œ->๋ถ„์œผ๋กœ ๋ฐ”๊พธ๊ธฐ"}</button>
     
     
    #3.9 Final Practice and Recap
     
    const root = document.getElementById("root");
    
    function MinutesToHours(){
        const [minutes, setMinutes] = React.useState(0);
        const [hours, setHours] = React.useState(0);
        const [flipped, setFlipped] = React.useState(false);
        const onChange = (event) => {
            if(!flipped) {
                setMinutes(event.target.value);
                setHours(event.target.value/60);
            }
            else {
                setHours(event.target.value);
                setMinutes(event.target.value*60);
            }
        };
        const reset = () => {
            setMinutes(0);
            setHours(0);
        };
        const onFlip = () => {
            setFlipped((current)=> !current);
            reset();
        };
        return (
            <div> 
                <label for="minutes">Minutes</label>
                <input value={minutes} id="minutes" placeholder="Minutes" type="number" onChange={onChange} disabled ={flipped}/>
                <label for="hours">Hours</label>
                <input value={hours} id="hours" placeholder="Hours" type="number"  onChange={onChange} disabled ={!flipped} />
                <button onClick={reset}>reset</button>
                <button onClick={onFlip}>{flipped? "๋ถ„->์‹œ๋กœ ๋ฐ”๊พธ๊ธฐ" : "์‹œ->๋ถ„์œผ๋กœ ๋ฐ”๊พธ๊ธฐ"}</button>
            </div>
        );  
    };
    
    function KmToMiles(){
        const [km, setKm] = React.useState(0);
        const [miles, setMiles] = React.useState(0);
        const [flipped, setFlipped] = React.useState(false);
        const onChange = (event) => {
            if(!flipped) {
                setKm(event.target.value);
                setMiles(event.target.value/1.609344);
            }
            else {
                setMiles(event.target.value);
                setKm(event.target.value*1.609344);
            }
        };
        const reset = () => {
            setKm(0);
            setMiles(0);
        };
        const onFlip = () => {
            setFlipped((current)=> !current);
            reset();
        };
        return (
            <div> 
                <label htmlFor="km">KM</label>
                <input value={km} id="km" placeholder="km" type="number" onChange={onChange} disabled ={flipped}/>
                <label htmlFor="miles">miles</label>
                <input value={miles} id="miles" placeholder="miles" type="number"  onChange={onChange} disabled ={!flipped} />
                <button onClick={reset}>reset</button>
                <button onClick={onFlip}>{flipped? "km->miles๋กœ ๋ฐ”๊พธ๊ธฐ":"miles->km๋กœ ๋ฐ”๊พธ๊ธฐ"}</button>
            </div>
        ); 
    };
    
    function App (){
        const [index, setIndex]=React.useState("xx");
        function onSelected (event){
            setIndex(event.target.value);
        }
        return (
            <div> 
                <h1>Super Converter</h1>
                <select value={index} onChange={onSelected}>
                    <option value="xx">
                        Selet
                    </option>
                    <option value="0">
                        Minutes to Hours
                    </option>
                    <option value="1">
                        Km to Miles
                    </option>
                </select>
    
                {index==="0" ? <MinutesToHours /> : null}
                {index==="1" ?<KmToMiles /> : null}
            </div>
        );  
    };
    ReactDOM.render(<App />, root)

     

    final practice ์™„๋ฃŒ 

     

     
     
    4 [2021 UPDATE] PROPS
    #4.0 Props
     
    props ๋Š” ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๋กœ๋ถ€ํ„ฐ ์ž์‹ ์ปดํฌ๋„ŒํŠธ์— ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค
    <MinutesToHours>, <KmToMiles> ์ปดํฌ๋„ŒํŠธ๋Š” ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์ธ App์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํ•„์š”๋กœ ํ•˜์ง€ ์•Š๋Š”๋‹ค. 
    ๋‘˜์€ ๋…๋ฆฝ์ ์œผ๋กœ ์กด์žฌํ•  ์ˆ˜ ์žˆ๋‹ค. 
     
    ์šฐ๋ฆฌ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ผ ํ•œ ์˜ˆ์‹œ๋ฅผ ๋งŒ๋“ค๊ฑฐ๋‹ค. 
     
    const root = document.getElementById("root");
    function Btn({bgcolor, text, big}){
        return <button style={{
            backgroundColor: bgcolor,
            color: "tomato",
            padding:"10px 20px",
            margin: "10px 5px",
            border: "1px solid black" ,
            borderRadius: 10,
            fontSize: big ? 18 : 16
        }}> {text} </button>;
    }
    function App (){
        return (
            <div> 
                <Btn text="Save Changes" bgcolor="white" big={true}/>
                <Btn text="Continue" bgcolor="black"  big={false}/>
            </div>
        );  
    }
    ReactDOM.render(<App />, root)
     
    ์—ฌ๊ธฐ๋ถ€ํ„ฐ 6-1๊นŒ์ง€ ์ •๋ฆฌํ–ˆ๋˜ ๋ถ€๋ถ„์ด ๋‹ค ๋‚ ๋ผ๊ฐ”๋‹ค... ์ง„์งœ ๋ˆˆ๋ฌผ๋‚œ๋‹ค....................
    ๋ญ ์–ด์ฉŒ๊ฒ ์–ด,, ๋‹ค์‹œ ์ •๋ฆฌํ•ด์•ผ์ง€.. 
    ๋‹น์žฅ ๋‚ด์ผ ํ•ด์ปคํ†ค์ธ๋ฐ ์™œ ๋‚˜์—๊ฒŒ ์ด๋Ÿฐ ์‹œ๋ จ์ด .. 
     
    #4.1 Memo
    const MemorizedBtn = React.memo(Btn);
    
    
    function App (){
        const [value, setValue] = React.useState("Save Changes");
        function changeValue(){
            setValue("Revert Changes");
        }
        return (
            <div> 
                <MemorizedBtn text={value} onClick={changeValue} />
                <MemorizedBtn text="์•ˆ๋…•" />
            </div>
        );  
    }
     
    onClick ์„ ์‚ฌ์šฉํ•œ ๋ฒ„ํŠผ๋งŒ rerender๋œ๋‹ค
    ์ „์ฒด๋ฅผ ๋‹ค rerenderingํ•˜๊ฒŒ ๋˜๋ฉด ์–ดํ”Œ์ด ๋Š๋ ค์งˆ ์ˆ˜๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ค‘์š”ํ•˜๋‹ค.
     
     
    #4.2 Prop Types
     
    <script type="text/babel">
        const root = document.getElementById("root");
        function Btn({text,onClick}){
            console.log(text," was rendered");
            return <button 
            onClick={onClick}
            style={{
                backgroundColor: "black",
                color: "tomato",
                padding:"10px 20px",
                margin: "10px 5px",
                border: "1px solid black" ,
                borderRadius: 10,
            }}
            > {text} </button>;
        }
        const MemorizedBtn = React.memo(Btn);
        MemorizedBtn.propTypes={
            text: PropTypes.string.isRequired,
            onClick: PropTypes.func,
        };
        function App (){
            const [value, setValue] = React.useState("Save Changes");
            function changeValue(){
                setValue("Revert Changes");
            }
            return (
                <div> 
                    <MemorizedBtn text={value} onClick={changeValue} />
                    <MemorizedBtn text="์•ˆ๋…•" />
                </div>
            );  
        }
        ReactDOM.render(<App />, root)
    </script>
     
    ์š”๊ธฐ ์ฐธ์กฐ 
     
    ํŒ€์›์˜ ์‹ค์ˆ˜ ๋ง‰์„ ์ˆ˜ ์žˆ์Œ
     
    import PropTypes from 'prop-types';
    
    MyComponent.propTypes = {
      // prop๊ฐ€ ํŠน์ • JS ํ˜•์‹์ž„์„ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
      // ์ด๊ฒƒ๋“ค์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ชจ๋‘ ์„ ํƒ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค.
      optionalArray: PropTypes.array,
      optionalBool: PropTypes.bool,
      optionalFunc: PropTypes.func,
      optionalNumber: PropTypes.number,
      optionalObject: PropTypes.object,
      optionalString: PropTypes.string,
      optionalSymbol: PropTypes.symbol,
    
      // ๋žœ๋”๋ง ๋  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๋“ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
      // ์ˆซ์ž(numbers), ๋ฌธ์ž(strings), ์—˜๋ฆฌ๋จผํŠธ(elements), ๋˜๋Š” ์ด๋Ÿฌํ•œ ํƒ€์ž…๋“ค(types)์„ ํฌํ•จํ•˜๊ณ  ์žˆ๋Š” ๋ฐฐ์—ด(array) (ํ˜น์€ ๋ฐฐ์—ด์˜ fragment)
      optionalNode: PropTypes.node,
    
      // React ์—˜๋ฆฌ๋จผํŠธ.
      optionalElement: PropTypes.element,
    
      // React ์—˜๋ฆฌ๋จผํŠธ ํƒ€์ž… (ie. MyComponent)
      optionalElementType: PropTypes.elementType,
    
      // prop๊ฐ€ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค์ž„์„ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
      // ์ด ๊ฒฝ์šฐ JavaScript์˜ instanceof ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
      optionalMessage: PropTypes.instanceOf(Message),
    
      // ์—ด๊ฑฐํ˜•(enum)์œผ๋กœ ์ฒ˜๋ฆฌํ•˜์—ฌ prop๊ฐ€ ํŠน์ • ๊ฐ’๋“ค๋กœ ์ œํ•œ๋˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
      optionalEnum: PropTypes.oneOf(['News', 'Photos']),
    
      // ์—ฌ๋Ÿฌ ์ข…๋ฅ˜์ค‘ ํ•˜๋‚˜์˜ ์ข…๋ฅ˜๊ฐ€ ๋  ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด
      optionalUnion: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.number,
        PropTypes.instanceOf(Message)
      ]),
    
      // ํŠน์ • ํƒ€์ž…์˜ ํ–‰๋ ฌ
      optionalArrayOf: PropTypes.arrayOf(PropTypes.number),
    
      // ํŠน์ • ํƒ€์ž…์˜ ํ”„๋กœํผํ‹ฐ ๊ฐ’๋“ค์„ ๊ฐ–๋Š” ๊ฐ์ฒด
      optionalObjectOf: PropTypes.objectOf(PropTypes.number),
    
      // ํŠน์ • ํ˜•ํƒœ๋ฅผ ๊ฐ–๋Š” ๊ฐ์ฒด
      optionalObjectWithShape: PropTypes.shape({
        color: PropTypes.string,
        fontSize: PropTypes.number
      }),
    
      // ์ถ”๊ฐ€ ํ”„๋กœํผํ‹ฐ์— ๋Œ€ํ•œ ๊ฒฝ๊ณ ๊ฐ€ ์žˆ๋Š” ๊ฐ์ฒด
      optionalObjectWithStrictShape: PropTypes.exact({
        name: PropTypes.string,
        quantity: PropTypes.number
      }),
    
      // ์œ„์— ์žˆ๋Š” ๊ฒƒ ๋ชจ๋‘ `isRequired`์™€ ์—ฐ๊ฒฐํ•˜์—ฌ prop๊ฐ€ ์ œ๊ณต๋˜์ง€ ์•Š์•˜์„ ๋•Œ
      // ๊ฒฝ๊ณ ๊ฐ€ ๋ณด์ด๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
      requiredFunc: PropTypes.func.isRequired,
    
      // ๋ชจ๋“  ๋ฐ์ดํ„ฐ ํƒ€์ž…์ด ๊ฐ€๋Šฅํ•œ ํ•„์ˆ˜๊ฐ’
      requiredAny: PropTypes.any.isRequired,
    
      // ์‚ฌ์šฉ์ž ์ •์˜ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๊ธฐ๋ฅผ ์ง€์ •ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
      // ๊ฒ€์‚ฌ ์‹คํŒจ ์‹œ์—๋Š” ์—๋Ÿฌ(Error) ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
      // `oneOfType`์•ˆ์—์„œ๋Š” ์ž‘๋™ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ `console.warn` ํ˜น์€ throw ํ•˜์ง€ ๋งˆ์„ธ์š”.
      customProp: function(props, propName, componentName) {
        if (!/matchme/.test(props[propName])) {
          return new Error(
            'Invalid prop `' + propName + '` supplied to' +
            ' `' + componentName + '`. Validation failed.'
          );
        }
      },
    
      // `arrayOf` ์™€ `objectOf ์— ์‚ฌ์šฉ์ž ์ •์˜ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๊ธฐ๋ฅผ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
      // ๊ฒ€์‚ฌ ์‹คํŒจ ์‹œ์—๋Š” ์—๋Ÿฌ(Error) ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
      // ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๊ธฐ๋Š” ๋ฐฐ์—ด(array) ํ˜น์€ ๊ฐ์ฒด์˜ ๊ฐ ํ‚ค(key)์— ๋Œ€ํ•˜์—ฌ ํ˜ธ์ถœ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
      // ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๊ธฐ์˜ ์ฒซ ๋‘ ๊ฐœ์˜ ๋ณ€์ˆ˜๋Š” ๋ฐฐ์—ด ํ˜น์€ ๊ฐ์ฒด ์ž์‹ ๊ณผ ํ˜„์žฌ ์•„์ดํ…œ์˜ ํ‚ค์ž…๋‹ˆ๋‹ค.
    
      customArrayProp: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
        if (!/matchme/.test(propValue[key])) {
          return new Error(
            'Invalid prop `' + propFullName + '` supplied to' +
            ' `' + componentName + '`. Validation failed.'
          );
        }
      })
    };
     
    #4.3 Recap 
    pass
     
    5 [2021 UPDATE] CREATE REACT APP
    #5.0 Introduction
    create-react-app์„ ์ด์šฉํ•˜๋ฉด ๊ฐœ๋ฐœ ์„œ๋ฒ„์— ์ ‘๊ทผํ•œ๋‹ค๋˜๊ฐ€, ์ž๋™์œผ๋กœ ์ƒˆ๋กœ๊ณ ์นจ์„ ํ•ด์ค€๋‹ค๋˜๊ฐ€ ์ฆ‰๊ฐ์ ์œผ๋กœ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์— css๋ฅผ ํฌํ•จ์‹œ์ผœ์ฃผ๋Š” ๋“ฑ ์•„์ฃผ ์ข‹๋‹ค..
     
    node.js์— ๊ฐ€์„œ ๋‹ค์šด๋กœ๋“œ ๋ฐ›๊ณ  node -v ๋กœ ํ™•์ธ ๊ทธ๋ฆฌ๊ณ  npx ๋„ ์ž…๋ ฅ
    ์‹คํ–‰์€ npm start
     
     
    ํ•„์š”์—†๋Š” ๊ฒƒ ๋‹ค ๋นผ๊ณ  ๋งŒ๋“  ver.
     
     
     
     
    #5.1 Tour of CRA
     

    Button.js

    import PropTypes from "prop-types";
    import style from "./Button.module.css"
    function Button({text}){
        return (
            <button className={style.btn}>{text}</button>
        );
    }
    
    Button.propTypes = {
        text : PropTypes.string.isRequired,
    };
    
    export default Button;
     
     
     
    app.js
     
    App.module.css 

     

    .title{
        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        font-size: 18px;
    }โ€‹
     
    ํŠน์ • ์ปดํฌ๋„ŒํŠธ๋ฅผ ์œ„ํ•œ css๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•ด์กŒ๋‹ค. 
     
     
    6 [2021 UPDATE] EFFECTS
    #6.0 Introduction
     
    ๋งˆ์ง€๋ง‰์œผ๋กœ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ์ด์•ผ๊ธฐ!
    ๋ฐ”๋€” ํ•„์š”๊ฐ€ ์—†๋Š” ์š”์†Œ๋“ค๊นŒ์ง€ ๋‹ค์‹œ ๋ Œ๋”๋ง ๋˜๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•จ์ด๋‹ค. 
     
     
     
     
     
    #6.1 useEffect
     
    ์•„๋ž˜ ์ฝ”๋“œ๋ž‘ ํ•ฉ์น ๋ž˜.. 
    ์ฝ”๋“œ๋ฅผ ์–ธ์ œ ์‹คํ–‰ํ•  ์ง€ ์šฐ๋ฆฌ๊ฐ€ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“œ๋Š” ๋„๊ตฌ!
     
     
    #6.2 Deps
     

    Dependency

    import {useState, useEffect} from "react";
    
    function App() {
      const [counter, setValue] = useState(0);
      const [keyword, setKeyword] = useState("");
      const onClick = () => setValue((prev)=>prev+1);
      const onChange = (event) => setKeyword(event.target.value);
      console.log("I run all the time");
      useEffect(()=>{
        console.log("CALL the API...");
      }, []);
      useEffect(()=>{
        console.log("Search for", keyword);
      }, [keyword]);
      return (
        <div>
          <input 
            value={keyword} 
            onChange={onChange} 
            type="text" 
            placeholder="Search here..." 
          />
          <h1> {counter} </h1>
          <button onClick={onClick} >click</button>
        </div>
      );
    }
    
    export default App;
     
    ํ‚ค์›Œ๋“œ๊ฐ€ ๋ณ€๊ฒฝํ• ๋•Œ๋งŒ ์•ˆ์˜ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋œ๋‹ค.
     
     
    ๊ทธ๋ƒฅ useEffect์— ๋„ฃ์€ CALL ~ ์€ ์ฒ˜์Œ ๋ Œ๋”๋ง ๋ ๋•Œ๋งŒ ํ•œ๋ฒˆ ์‹คํ–‰๋œ๋‹ค. Search~ ๋Š” input ๋ฐ•์Šค ์•ˆ์˜ ๊ฐ’์ด ๋ฐ”๋€” ๋•Œ ์‹คํ–‰๋˜๊ณ  I run all~์€ ์„œ์นญ์„ ํ• ๋•Œ๋“ , ๋ฒ„ํŠผ์„ ํด๋ฆญํ• ๋•Œ๋“  ๋ฌด์–ธ๊ฐ€ ๋ฐ”๋€Œ๋ฉด ํ•ญ์ƒ ์ž‘๋™ํ•œ๋‹ค.

     

    useEffect(()=>{
        if(keyword.length>5)
          console.log("Search for", keyword);
      }, [keyword]);

    ์ด๋ ‡๊ฒŒ ์กฐ๊ฑด๋„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค. 

     

    [] ์ด ์•ˆ์˜ ๊ฒƒ์„ ๋ฆฌ์•กํŠธ๊ฐ€ ์ง€์ผœ๋ณด๊ณ  ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ์‰ฝ๋‹ค. ์•„๋ฌด๊ฒƒ๋„ ์—†๋Š” ๊ฑด ์ง€์ผœ๋ด๋„ ์•„๋ฌด์ผ์ด ์—†์œผ๋‹ˆ๊นŒ ์ฒ˜์Œ ์‹คํ–‰๋  ๋•Œ๋งŒ ์ฝ˜์†”๋กœ๊ทธ๊ฐ€ ์ž‘๋™ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ๋ฆฌ์ŠคํŠธ์ด๊ธฐ ๋•Œ๋ฌธ์— [counter, keyword] ์ด๋ ‡๊ฒŒ ๋„ฃ์–ด๋„ ๋œ๋‹ค. ๋‘˜ ์ค‘ ํ•˜๋‚˜๊ฐ€ ์‹คํ–‰๋  ๋•Œ ์ฝ”๋“œ๊ฐ€ ์ž‘๋™ํ•œ๋‹ค. 

     

     

    #6.3 Recap
     
    #6.4 Cleanup
    import {useState, useEffect} from "react";
    
    function Hello(){
      useEffect(()=>{
        console.log("I'm here :)");
        return () => console.log("destroyed :(")
      },[]);
      return <h1>Hello</h1>
    }
    function App() {
      const [showing, setShowing] = useState(false);
      const onClick = () => setShowing((prev)=>!prev);
     
      return (
        <div>
          {showing ? <Hello /> : null}
          <button onClick={onClick}>{showing?"hide":"show"}</button>
        </div>
      );
    }
    
    export default App;
     
    useEffect ํ•จ์ˆ˜์˜ return์œผ๋กœ ํ•จ์ˆ˜๋ฅผ ์ฃผ๋ฉด, hide๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ destroyed :( ๊ฐ€ ํ”„๋ฆฐํŠธ ๋œ๋‹ค. 
    ์ด๊ฒƒ์„ Cleanup function์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. 
     
     
    import {useState, useEffect} from "react";
    
    function Hello(){
    
      function effectFn(){
        console.log("created :)");
        return byeFn
      }
      function byeFn(){
        console.log("bye~ .. ")
      }
      useEffect(effectFn,[]);
      return <h1>Hello</h1>
    }
    function App() {
      const [showing, setShowing] = useState(false);
      const onClick = () => setShowing((prev)=>!prev);
     
      return (
        <div>
          {showing ? <Hello /> : null}
          <button onClick={onClick}>{showing?"hide":"show"}</button>
        </div>
      );
    }
    
    export default App;
     
    ํ•จ์ˆ˜๋ฅผ ๋”ฐ๋กœ ๋นผ์„œ ์กฐ๊ธˆ ๋” ์ง๊ด€์ ์œผ๋กœ ๋ณด์ด๊ฒŒ ํ•œ ์ฝ”๋“œ 
     
    ๋‹ˆ๊ผฌsays
    react ์•ฑ์„ ๋งŒ๋“ค ๋•Œ ์ด byeFn์ด ์ฃผ๋กœ ํ•„์š”ํ•˜์ง€๋Š” ์•Š๋‹ค. ๊ฐ€๋” ํ•ด์•ผํ•  ๋•Œ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค.
    ๋ณดํ†ต์€ ํ•จ์ˆ˜ ๋”ฐ๋กœ ์•ˆ๋นผ๊ณ  useEffect์•ˆ์— ๋‹ค ๋„ฃ์–ด๋ฒ„๋ฆฐ๋‹ค. 
     
    7 [2021 UPDATE] PRACTICE MOVIE APP
    #7.0 To Do List part One
    import { useState } from "react";
    
    function App() {
      const [toDo, setToDo] = useState("");
      const [toDos, setToDos] = useState([]);
      const onChange = (event) => setToDo(event.target.value);
      const onSubmit = (event) => {
        event.preventDefault();
        if (toDo === "") {
          return;
        }
        setToDos((currentArray) => [toDo, ...currentArray]);
        setToDo("");
      };
      return (
        <div>
          <h1>My To Dos ({toDos.length})</h1>
         
          <form onSubmit={onSubmit}>
            <input
              onChange={onChange}
              value={toDo}
              type="text"
              placeholder="Write your to do..."
            />
            <button>Add To Do</button>
          </form>
        </div>
      );
    }
    
    export default App;
     
    toDo๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ์—ญํ• ์„ ํ•˜๋Š” ํ•จ์ˆ˜์ธ setToDo๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค. ์ง์ ‘์ ์ธ ์ˆ˜์ • x
    setToDos ํ•จ์ˆ˜์—์„œ currentArray ๋กœ ํ˜„์žฌ ์ƒํƒœ๋ฅผ ๋ถˆ๋Ÿฌ์™€์„œ ์ƒˆ๋กœ ๋ฐ›์€ toDo๋ฅผ ์•ž์—์„œ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค. 
     
       setToDos((currentArray) => [toDo, ...currentArray]);
       setToDo("");
     
    ์ด ๋‘๊ฐœ๋ฅผ ๋น„๊ตํ•ด๋ณด์ž๋ฉด,
     
    ์šฐ์„  setToDo๋Š” ๋‹จ์ˆœ์ด ๊ฐ’์„ ๋ณด๋‚ด๋Š” ๊ฒƒ์ด๋‹ค. 
    ์ด์— ๋ฐ˜ํ•ด setToDos๋Š” ํ•จ์ˆ˜๋ฅผ ๋ณด๋‚ด๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.
    ํ•จ์ˆ˜๋ฅผ ๋ณด๋‚ผ๋•Œ react.js๋Š” ํ•จ์ˆ˜์˜ ์ฒซ๋ฒˆ์งธ argument๋กœ ํ˜„์žฌ state๋ฅผ ๋ณด๋‚ธ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์šฐ๋ฆฐ ์ด๊ฒƒ์„ ์ด์šฉํ•ด์„œ ์ƒˆ๋กœ์šด toDos๋ฅผ ๋งŒ๋“ค์–ด returnํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค. 
     
     
    #7.1 To Do List part Two
     
    import { useState } from "react";
    
    function App() {
      const [toDo, setToDo] = useState("");
      const [toDos, setToDos] = useState([]);
      const onChange = (event) => setToDo(event.target.value);
      const onSubmit = (event) => {
        event.preventDefault();
        if (toDo === "") {
          return;
        }
        setToDos((currentArray) => [toDo, ...currentArray]);
        setToDo("");
      };
      return (
        <div>
          <h1>My To Dos ({toDos.length})</h1>
         
          <form onSubmit={onSubmit}>
            <input
              onChange={onChange}
              value={toDo}
              type="text"
              placeholder="Write your to do..."
            />
            <button>Add To Do</button>
          </form>
          <hr />
          {toDos.map((item, index)=>
            <li key={index}>{item}</li>
            
          )}
           
        </div>
      );
    }
    
    export default App;
     
     
     
    #7.2 Coin Tracker
     
     ์ด๋ฒˆ์—” react์—์„œ ์ฒ˜์Œ์œผ๋กœ api๋ฅผ ๊ฐ€์ ธ์™€์„œ ๋„์›Œ๋ณผ ๊ฒƒ์ด๋‹ค.
    ์ฒ˜์Œ ์‹คํ–‰๋  ๋•Œ๋งŒ render์‹œํ‚ค๊ณ  ์‹ถ๊ธฐ ๋•Œ๋ฌธ์— useEffect๋ฅผ ์ด์šฉํ•œ๋‹ค. 
     
    api ์ฃผ์†Œ
     
    import { useState, useEffect } from "react";
    
    function App() {
      const [loading, setLoading]= useState(true);
      const [coins, setCoins] = useState([])
      useEffect(() => {
        fetch("http://api.coinpaprika.com/v1/tickers")
        .then((response) => response.json())
        .then((json) => {
          setCoins(json);
          setLoading(false);
        });
      }, []);
      return (
          <div>
            <h1>The Coins!({coins.length})</h1>
            {loading ? <strong>Loading...</strong>: 
            <ul>
              {coins.map((coin)=> (
                <li>
                  {coin.name} ({coin.symbol}): ({coin.quotes.USD.price}) USD
                </li>
              ))}
            </ul>
            }
          </div>
      );
    }
    
    export default App;โ€‹
     
    ์•ˆ๋ถˆ๋Ÿฌ์™€์ ธ์„œ ๊ฝค๋‚˜ ๊ณ ์ƒํ–ˆ๋Š”๋ฐ, ๋‚ด๊ฐ€ ์‹ค์ˆ˜ํ•œ ๋ถ€๋ถ„์€ map์˜ arrow function ๋ถ€๋ถ„์ด์—ˆ๋‹ค. ()=>{} ์ด๋ ‡๊ฒŒ ์ผ์—ˆ๋Š”๋ฐ, map์—์„œ ๊ทธ๋ ‡๊ฒŒ ์ผ๋”๋‹ˆ ๋ชป๋ถˆ๋Ÿฌ์™”๋‹ค. 
     
     
     
    ๋ˆ์„ ์ž…๋ ฅํ•˜๊ณ ๋‚˜์„œ ์ฝ”์ธ ์ข…๋ฅ˜๋ฅผ select ํ•˜์—ฌ ๋ช‡๊ฐœ์˜ ์ฝ”์ธ์„ ์‚ด ์ˆ˜ ์žˆ๋Š”์ง€ ๊ณ„์‚ฐํ•ด์ฃผ๋Š” ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ์งœ๋ดค๋‹ค 
     
     
    import { useState, useEffect } from "react";
    
    function App() {
      const [coins, setCoins] = useState([])
      const [input, setInput] = useState(0);
     
      const [selected, setSelected] = useState(0);
      function onChanged(event){
        setInput(event.target.value);
        console.log(input);
      }
     
      function onSelected(event){
        setSelected(event.target.value);
        console.log(selected);
      }
    
      useEffect(() => {
        fetch("http://api.coinpaprika.com/v1/tickers")
        .then((response) => response.json())
        .then((json) => {
          setCoins(json);
        
        });
      }, []);
      return (
          <div>
            <h1>The Coins!({coins.length})</h1>
            <form>
              <input value={input} onChange={onChanged} type="number" placeholder="input money"></input>
             
            </form>
            {input!==0 ? 
              
              <div>
                <select value={selected} onChange={onSelected}>
                  {coins.map((coin, index)=> (
                    <option key={index} value={coin.quotes.USD.price}>
                      {coin.name} ({coin.symbol}): ({coin.quotes.USD.price}) USD
                    </option>
                  ))}
                </select>
                <h1>{input/selected}</h1>  
               
              </div>
              : null
            }
           
          </div>
      );
    }
    
    export default App;
     
     
    ์›๋žœ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์•„๋ž˜ select๊ฐ€ ๋‚˜์˜ค๊ฒŒ ํ•˜๊ณ  ์‹ถ์—ˆ๋Š”๋ฐ, ๊ฒฐ๊ตญ์€ ๊ทธ ๊ธฐ์ค€์„ input์œผ๋กœ ํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค. 
    ํ•ด์ปคํ†ค์ด ๋‹ค๊ฐ€์˜ค๋‹ˆ ์‹œ๊ฐ„๋•Œ๋ฌธ์— ์ซ„๋ฆฐ๋‹ค ....ใ…œ
     
     
     
     
    #7.3 Movie App part One
     
    import { useState, useEffect } from "react";
    
    function App() {
      const [movies, setMovies] = useState([])
      const [loading, setLoading] = useState(true);
     
      useEffect(() => {
        fetch("https://yts.mx/api/v2/list_movies.json?minimum_rating=8.8&sort_by=year")
        .then((response) => response.json())
        .then((json) => {
          console.log(json);
        
        });
      }, []);
      return (
        <div>
          {loading ? <h1>Loading...</h1> : null}
        </div>
      );
    }
    
    export default App;
     
     
    1. ์—ฌ๊ธฐ๊นŒ์ง€ ์ž‘์„ฑํ•˜๊ณ  ์šฐ์„  console ์‚ดํŽด๋ณด๊ธฐ 
    ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ์ •๋ณด๋Š” data.movies์— ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
     
     
    useEffect(() => {
        fetch("https://yts.mx/api/v2/list_movies.json?minimum_rating=8.8&sort_by=year")
        .then((response) => response.json())
        .then((json) => {
          setMovies(json.data.movies);
          console.log(movies);
          setLoading((cur)=>!cur);
        });
      }, []);
     
     movies ์— ๋„ฃ์–ด์ฃผ๊ธฐ 
     
    import { useState, useEffect } from "react";
    
    function App() {
      const [movies, setMovies] = useState([])
      const [loading, setLoading] = useState(true);
      const getMovies = async() => {
        const json = await(await fetch("https://yts.mx/api/v2/list_movies.json?minimum_rating=8.8&sort_by=year")).json();
        setMovies(json.data.movies);
        setLoading(false);
      }
      useEffect(() => {
        getMovies();
      }, []);
      return (
        <div>
          {loading ? <h1>Loading...</h1> : null}
        </div>
      );
    }
    
    export default App;
     
     .then() ๋Œ€์‹  getMovies ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค. 
    import { useState, useEffect } from "react";
    
    function App() {
      const [movies, setMovies] = useState([])
      const [loading, setLoading] = useState(true);
      const getMovies = async() => {
        const json = await(await fetch("https://yts.mx/api/v2/list_movies.json?minimum_rating=8.8&sort_by=year")).json();
        setMovies(json.data.movies);
        setLoading(false);
      }
      useEffect(() => {
        getMovies();
      }, []);
      console.log(movies);
      return (
        <div>
          {loading 
          ? <h1>Loading...</h1> 
          : <div>
            {movies.map(movie=>
              <div key={movie.id}>
                <img src={movie.medium_cover_image}></img>
                <h2>{movie.title}</h2>
                <p>{movie.summary}</p>
                <ul>
                  {movie.genres.map((g)=>
                  <li key={g}>{g}</li>)}
                </ul>
              </div>
               
              )}
    
          </div>
          }
        </div>
      );
    }
    
    export default App;โ€‹
     
     
     
     
    #7.4 Movie App part Two
     
    App.js
    import { useState, useEffect } from "react";
    import Movie from "./Movie";
    function App() {
      const [movies, setMovies] = useState([])
      const [loading, setLoading] = useState(true);
      const getMovies = async() => {
        const json = await(await fetch("https://yts.mx/api/v2/list_movies.json?minimum_rating=8.8&sort_by=year")).json();
        setMovies(json.data.movies);
        setLoading(false);
      }
      useEffect(() => {
        getMovies();
      }, []);
      console.log(movies);
      return (
        <div>
          {loading ? <h1>Loading...</h1> 
          : <div>
            {movies.map(movie=>
              <Movie
                key={movie.id}
                coverImg={movie.medium_cover_image}
                title={movie.title}
                summary={movie.summary} 
                genres={movie.genres}
              />
            )}
            </div>
          }
        </div>
      );
    }
    
    export default App;
     
    Movie.js
    import PropTypes from "prop-types";
    
    function Movie({ coverImg, title, summary, genres}){
        return(
        <div>
            <img src={coverImg} alt={title}></img>
            <h2>{title}</h2>
            <p>{summary}</p>
            <ul>
                {genres.map((g)=>
                    <li key={g}>{g}</li>)}
            </ul>
        </div>
        );
    }
    
    Movie.propTypes={
        coverImg: PropTypes.string.isRequired,
        title: PropTypes.string.isRequired,
        summary:  PropTypes.string.isRequired,
        genres: PropTypes.arrayOf(PropTypes.string).isRequired
    
    };
    
    export default Movie;
     key ๋Š” App.js ์—์„œ๋งŒ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.
    img ์— alt ๊ผญ ๋„ฃ์–ด์ค˜์•ผ ํ•œ๋‹ค.
     
     
    #7.5 React Router
     
    ๋‹ค์Œ์€ ๋ผ์šฐํŒ…!!
    npm install react-router-dom ์„ ์ž…๋ ฅํ•˜์—ฌ ๋‹ค์šด๋กœ๋“œ ํ•œ๋‹ค. 
     
     
     
    route ํด๋”๋ฅผ ๋งŒ๋“ค์–ด ํŽ˜์ด์ง€๋ณ„ ํŒŒ์ผ์— ์ฝ”๋“œ๋ฅผ ๋„ฃ์–ด๋‘๊ณ  
    component ํด๋”๋ฅผ ๋งŒ๋“ค์–ด ์•„๊นŒ ๋ถ„๋ฆฌํ•ด๋’€๋˜ ์ปดํฌ๋„ŒํŠธ์ธ Movie.js ๋ฅผ ๋„ฃ์–ด์ค€๋‹ค. 
    App.js๋Š” ์ด์ œ router์„ renderํ•ด์ฃผ๋Š” ์—ญํ• ์„ ํ•˜๊ฒŒ ๋œ๋‹ค. 
    router ์€ URL์„ ๋ณด๊ณ  ์žˆ๋Š” component๋‹ค.
     
    import {
      BrowserRouter as Router,
      Switch,
      Route,
      Link
    } from "react-router-dom";
    import Home from "./routes/Home";
    import Detail from "./routes/Detail";
    function App() {
      return <Router>
        <Switch>
        <Route path="/movie">
            <Detail />
          </Route>
          <Route path="/">
            <Home />
          </Route>
        </Switch>
      </Router>;
    }
    export default App;
     
    ๋ผ์šฐํŒ… ๋„ˆ๋ฌด ์‰ฌ์šด๋ฐ..? ๊ทธ๋™์•ˆ spring์—์„œ mybatis๋กœ mapping ํ•˜๊ณ  ์žˆ๋˜๊ฑฐ ์ƒ๊ฐํ•˜๋‹ˆ๊นŒ ๋„ˆ๋ฌด ๋นก์นœ๋‹ค. ....  . ..
     
    ๐Ÿ“
    2022/12/02 ํ•ด์ปค์›น์‚ฌ์ดํŠธ ์—…๋ฐ์ดํŠธ 
    react-router-dom์ด ์—…๋ฐ์ดํŠธ ๋˜๋ฉด์„œ ๋ผ์šฐํŒ… ๋ฐฉ์‹์ด ์ข€ ๋ฐ”๋€Œ์—ˆ๋‹ค. switch ๋Œ€์‹  routes๋ฅผ ์จ์ค˜์•ผํ•˜๊ณ  Route์˜ element๋กœ ํƒœ๊ทธ ์•ˆ์— ์ž…๋ ฅํ•ด์•ผํ•จ.
     
    import {
      BrowserRouter as Router,
      Route,
      Routes,
    } from "react-router-dom";
    import HomePage from "./routes/HomePage";
    import AboutPage from "./routes/AboutPage";
    
    function App() {
      return <Router>
        <Routes>
          <Route path="/" element={<HomePage />}>
          </Route>
          <Route path="/about" element={<AboutPage />}>
          </Route>
        </Routes>
      </Router>;
    }
    export default App;
     
     
     
     
    html ์—์„œ ์‚ฌ์šฉํ•œ ๋ฐฉ์‹์œผ๋กœ <a href=""> ์œผ๋กœ ํ•˜๋ฉด ์ „์ฒด๊ฐ€ ์ƒˆ๋กœ๊ณ ์นจ๋œ๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ๋‹ค. 
    ์ด๊ฑธ ๋ณด์™„ํ•œ๊ฒŒ ๋ฐ”๋กœ <Link>์ด๋‹ค. 
     
    import PropTypes from "prop-types";
    import {Link} from "react-router-dom";
    
    function Movie({coverImg, title, summary, genres}){
        return(
        <div>
            <img src={coverImg} alt={title}></img>
            <h2>
                <Link to="/movie">{title}</Link>
            </h2>
            <p>{summary}</p>
            <ul>
                {genres.map((g)=>
                    <li key={g}>{g}</li>)}
            </ul>
        </div>
        );
    }
     
    ์ด๋ ‡๊ฒŒ Link to ๋กœ ๊ฐ์‹ธ์ฃผ๋ฉด ์ƒˆ๋กœ๊ณ ์นจ๋˜์ง€ ์•Š๋Š”๋‹ค. 
     
     
     
    #7.6 Parameters
     
    ์ด๋ฒˆ์—” movie/123 ์ด๋Ÿฐ์‹์œผ๋กœ dynamic url ์„ ๋งŒ๋“ค์–ด๋ณผ ๊ฒƒ์ด๋‹ค. 
     
     <Link to={`/movie/${id}`}>{title}</Link>
     
    property๋กœ id๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  (key๋ž‘ ๋˜‘๊ฐ™์€ id์จ๋„ ์ƒ๊ด€ ์—†์Œ)
    ๋งํฌ๋ฅผ ์ˆ˜์ •ํ•ด์ฃผ๋ฉด 
     ์ž˜ ๋‚˜์˜จ๋‹ค.
     
    <Route path="/movie/:id">
    	<Detail />
    </Route>
     
    :id ์ด ๋ถ€๋ถ„์— ์˜ค๋Š” ๊ฐ’์ด ๋ญ”์ง€ ํ™•์ธํ•˜๋Š” ๊ฑด ์•„์ฃผ ์‰ฝ๋‹ค.
     
    #7.7 Publishing
     
     github pages๋Š” github์—์„œ ์ œ๊ณตํ•˜๋Š” ๋ฌด๋ฃŒ ์„œ๋น„์Šค
    npm i gh-pages
     
     
    ์šฐ์„  ๊นƒํ—™์— repo ํ•˜๋‚˜ ํŒŒ์„œ ๊ทธ๋™์•ˆ ์ž‘์—…ํ•œ๊ฑฐ ๋ชจ๋‘ ์˜ฌ๋ ค๋‘๊ณ 
     
     
    package.json ์˜ ์ œ์ผ ์•„๋žซ๋ถ€๋ถ„์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ถ”๊ฐ€ํ•œ๋‹ค. 
        ]
      },
      "homepage":"https://chamroro.github.io/ReactMovieService"
    }
     
     "scripts": {
        "start": "react-scripts start",
        "build": "react-scripts build",
        "test": "react-scripts test",
        "eject": "react-scripts eject",
        "deploy": "gh-pages -d build",
        "predeploy": "npm run build"
      },

    ์œ„์™€ ๊ฐ™์ด ์ถ”๊ฐ€ํ•˜๋ฉด build ํด๋”๋ฅผ ์‚ญ์ œํ•˜๊ณ  npm run deploy์ด๋ ‡๊ฒŒ ํ•˜๋ฉด predeploy ๊ฐ€ ๋œ ํ›„์— buld๋ฅผ ํ•œ๋‹ค. 

     

     
    ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์›น์‚ฌ์ดํŠธ๊ฐ€ ์—…๋ฐ์ดํŠธ ๋˜๊ฒŒ ๋˜๋Š”๋ฐ, ์ด๊ฑด 5๋ถ„์ •๋„ ๊ฑธ๋ฆฐ๋‹ค๊ณ  ํ•œ๋‹ค. 
     
    ๋ฌด์–ธ๊ฐ€ ์ˆ˜์ •์„ ํ•œ ๋’ค์— npm run deploy๋ฅผ ํ•ด์ฃผ๋ฉด ์ž๋™์œผ๋กœ ํ”„๋กœ์ ํŠธ๊ฐ€ build๊ฐ€ ๋˜๊ณ  ์ž๋™์œผ๋กœ github ioํŽ˜์ด์ง€์— ์˜ฌ๋ผ๊ฐ€๊ฒŒ ๋œ๋‹ค.
     
    #7.8 Conclusions
     
    #7.9 Styles
     
    ์Šคํƒ€์ผ ๋จน์ด๊ธฐ ์™„!
     
     
    #7.10 Next Steps
     
    react.js๋Š” ์—…๋ฐ์ดํŠธ๊ฐ€ ๋˜์–ด๋„ ์ด์ „ ๋ฐฉ์‹์„ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•  ์ˆ˜๊ฐ€ ์žˆ๋Š”๋ฐ, ์ด๊ฑด ์—…๋ฐ์ดํŠธ ๋  ๋•Œ๋งˆ๋‹ค ์ถ”๊ฐ€๋งŒ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. 
    useState์™€ useEffect ๊ฐ€ ๋ฒ ์ŠคํŠธ ์กฐํ•ฉ์ด๊ณ , ์˜›๋‚  ๋ฐฉ์‹์€ this, binding, constructor๋“ฑ ์•Œ์•„์•ผํ•˜๋Š” ๊ฒƒ๋“ค์ด ๋งŽ๋‹ค.
    react.js๋Š” ์ฒ˜์Œ๋ถ€ํ„ฐ props์™€ state๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์—ˆ๊ณ  ์˜ˆ์ „๋ฐฉ์‹์€ ๊ทธ๋ƒฅ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋‹ค๋ฅธ ๋ฐฉ์‹์ผ ๋ฟ์ด๋‹ค. 
    ๋‹ค์Œ ์˜์ƒ๋“ค์€ ์˜ˆ์ „ ๋ฐฉ์‹์œผ๋กœ ๊ฐ™์€ ์•ฑ์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ๋‚˜์˜ค๋Š” ๊ฒƒ์ด๋‹ค. 
    ๋”ฐ๋ผ์„œ,., ๋‚œ ์•ˆํ• ๊ฑฐ๋‹ค 
     
     
     
     
     
     
     
     
     
     
     
    ๋งˆ์ง€๋ง‰์œผ๋กœ ๋‚˜์˜ ํ”„๋กœ์ ํŠธ๋ฅผ ์˜ฌ๋ฆฌ๋ฉฐ 
    ํ•ด์ปคํ†ค ๋ฒผ๋ฝ์น˜๊ธฐ ๋! 

     

    React App

     

    chamroro.github.io

     

    ๋ฐ˜์‘ํ˜•

    ๋Œ“๊ธ€