๐Ÿค Web/๐ŸŒ React

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

chamroro 2022. 8. 19. 00:04

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

 

 

 

 

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

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

 

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

 

๋Ÿฌ๋‹์ปค๋ธŒ๊ฐ€ ๋†’์€ 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

 

๋ฐ˜์‘ํ˜•