리액트 명령어
# (최초1번) npm install -g create-react-app
# react 프로젝트 만들기 :
npx create-react-app 프로젝트명
# react 프로젝트 실행하기 :
cd 프로젝트명 (프로젝트명 폴더로 들어가기)
npm start (react 서버 가동 명령어))
# react 프로젝트 중단하기 :
vscode 터미널 창에서 : ctrl + c (2번이상 타이핑하고 엔터)
리액트 특징
# React(페이스북, 점유율1위) / Vue(개인, 구글퇴사) / Angular js(구글 x)
# React / Vue : SPA(Single Page Application) 개발
# (html 1장으로 개발 : 메뉴: 홈/로그인/회원가입 페이지 등)
# (각 페이지가 js 코딩되어 -> html 로 바뀜)
npx create-react-app hello-world
입력 후 성공 시 뜨는 화면
cd hello-world
npm start 서버 시작 명령어
입력 후 성공시 뜨는 화면
리액트 서버 실행
서버 중단 명령어 ctrl + c
y 누르거나 ctrl + c 두번 누르기
App.js의 div태그에서 내용 바꾸면 화면도 바뀜
확장 프로그램 추가 설치
React develop tool 설치
1) Auto Import / 2) ES7+ React/Redux / 3) TODO Highlight 플러그인 설치
크롬 웹 스토어 접속
https://chrome.google.com/webstore/category/extensions?hl=ko
확장 프로그램 관리 들어가서
파일 URL에 대한 액세스 허용 체크
리액트 디버깅 정보 확인
터미널 닫을 때는 휴지통 아이콘 클릭
001
App.js
(원하는 js 주석해제)
// 리액트 주소 : http://localhost:3000
// http://(프로토콜),
// localhost(인터넷주소 예)naver.com ) : 개인pc 인터넷주소
// 3000 : 포트번호(0 ~ 90000) , :80(이것만 생략)
// App.js : 리액트의 1st 페이지(사이트 home 페이지)
// => 리액트 서버가 가동되고 처음으로 실행되는 페이지(js)
// 리액트 페이지(js) : 컴포넌트(==페이지)
// 사용법 :
// function 컴포넌트명() {
// return {
// <div>내용</div>
// }
// }
import logo from './logo.svg';
import './App.css';
// 자식 컴포넌트(페이지) import
// import Home from "./components/Home.js";
import Home from "./components/Home.js"
// 자식 컴포넌트 import
import Header from "./components/Header";
import Footer from './components/Footer';
import B_Home2 from './components/B_Home2';
import C_Exam from './components/C_Exam';
import D_ImportComp from './components/D_ImportComp';
// 최상위 부모 컴포넌트 : App(App.js)
// 자식 컴포넌트 : Home(Home.js)
function App() {
return (
<div className="App">
<div>
<h1>Start React 200!</h1>
<p>HTML 적용하기</p>
</div>
{/* 머리말 */}
{/* <Header></Header> */}
{/* 주석 : ctrl + / */}
{/* Home.js 컴포넌트 태그 */}
{/* 본문 */}
{/* <Home></Home> */}
{/* <B_Home2></B_Home2> */}
{/* TODO: 연습문제 */}
{/* <C_Exam></C_Exam> */}
{/* <D_ImportComp></D_ImportComp> */}
{/* TODO: 꼬리말 컴포넌트 정의해서 넣으세요
이름 : Footer
*/}
<Footer></Footer>
</div>
);
}
export default App;
Home.js
리액트 페이지(컴포넌트) 단축키 rfce
// 리액트 페이지(컴포넌트) 단축키 : rfce
// TODO: 모든 자료형 출력해보기(출력되는것/안되는것)
// 자식 컴포넌트
import React from 'react'
function Home() {
// TODO: 변수를 정의하는 곳 : 여기
let array = ["a", "b", "c"]; // 일반변수
// 리액트 특징 : 변수값 + html 태그를 같이 사용이 가능함(JSX 표현식)
let input = <b>문자열 출력되나요?</b>;
// TODO: 함수를 정의하는 곳 : 여기
// 함수선언식 : function 함수명(){}
// 함수표현식 : let 함수명 = function(){};
// 화살표함수 : let 함수명 = () => {}
// 화살표함수 단축키 : nfn
const testFunc = () => {
return "함수입니다.";
}
// 클릭 이벤트 함수
// nfn
const myClick = () => {
alert("클릭했어요!!!");
}
// TODO: html 태그 + JSX 표현식({}) : return 안에 코딩함
// TODO: 웹브라우저 화면에 표시되는 영역
return (
<div>
{/* 주석 : ctrl + / */}
{/* 1) 문자열 출력 : O */}
{/* 사용법 : {"문자열"} */}
{"문자열 출력되나요!!!"}
<br/>
{input}
<br/>
{<b>이것도 출력될까요?</b>}
<br/>
{/* 2) 숫자 출력 : O */}
{1 * 2 + 3 - 2}
<br/>
{/* 3) 문자열 붙이기 : + */}
{"abc" + "가나다"}
<br/>
{/* 4) JSX 표현식 : {<태그>{문자열}</태그>} : O */}
{<b>{"안녕하세요"}</b>}
<br/>
{/* 5) 배열 출력 : O */}
{["가", "나", "다"]}
<br/>
{[1,2,3]}
<br/>
{array}
<br/>
{/* 6) 함수 출력 : */}
{/* 함수의 사용 : 함수명() : O */}
{testFunc() + " 이것도 될까요?"}
<br/>
{/* 7) 3항 연산자 : 조건식(축약형) : O */}
{/* 사용법 : (조건식==true)? 참 : 거짓; */}
{true? "true" : "false"}
<br/>
{false? "true" : "false"}
<br/>
{/* 8) html 태그 속성의 값으로 {} 넣어보기 : */}
<br/>
<button onClick={myClick}>클릭하세요</button>
<br/>
{/* 9) 자바스크립트 내장 함수 */}
{console.log("이것도 출력될까요?")}
<br/>
{/* 오늘 요일(1 ~ 7) : new Date() */}
{new Date().getDay()}
<br/>
{new Date().getFullYear() + "년"}
<br/>
{(new Date().getMonth()+1) + "월"}
{/* ------------------------------------------- */}
{/* 화면에 출력 안되는 것 */}
{/* ------------------------------------------ */}
{/* 10) 참/거짓(bool/boolean) : X */}
{/* 해결책 : 참/거짓 -> 문자열 로 변경해서 출력 */}
{true}
{/* 11) 객체 출력 : x , 에러 발생 */}
{/* 해결책 : 객체 -> 문자열 로 변경해서 출력 */}
{/* {{name:"홍길동", email:"hong@naver.com"}} */}
{/* 12) 조건문 : if문 : x */}
{/* 해결책 : 3항 연산자 */}
{/* {if(true) {return "true"}} */}
{/* 13) 반복문 : for문 : x */}
{/* 해결책 : map() 함수 가능 */}
{/* {for(let i=1;i<2;i++){console.log("aaa")}} */}
</div>
)
}
export default Home
결과
B_Home2
// B_Home2.js : 자식
// rfce
// TODO: 화면 바인딩
import { useState } from "react";
function B_Home2() {
// TODO: 변수를 정의하는 곳 : 여기
// 최초 1번만 정상적으로 화면에 표시
// 수정 -> 화면에 수정된 값이 보이지 않음
let hello = "안녕하세요"; // 일반변수
// 바인딩 변수 : 리액트에서는 화면에서 수정이 일어났을때 정상적으로
// 보이게 만들어 주는 변수
// 사용법 : let [변수명, 수정함수] = useState("초기값")
let [element, setElement] = useState("안녕");
// TODO : 함수 정의 : 여기
// nfn
// 화면 바인딩 없음 : 수정해서 화면에 나타나지 않음
const myClick = () => {
hello = "안녕하세요2";
}
// nfn
// TODO: 화면 바인딩 있음 : 수정하면 화면에 나타남
const myClick2 = () => {
// 리액트의 수정함수
setElement("안녕2");
}
// TODO: 웹브라우저 화면에 나오는 부분 : 아래
return (
<div>
{hello}
<button onClick={myClick}>클릭해보세요</button>
<br/>
{element}
<button onClick={myClick2}>클릭해보세요2</button>
<br/>
</div>
)
}
export default B_Home2
결과
클릭 후
C Exam
// C_Exam.js : 자식 컴포넌트
import { useState } from "react";
// rfce
// TODO: 연습문제
// TODO : 클릭시 아래 결과대로 코딩하세요
// TODO : 최초화면 : "안녕하세요"
// TODO : 결과 : "안녕"
// TODO: 1) 바인딩 변수 정의
function C_Exam() {
// TODO: 변수 정의 : 여기
// useState()
// 바인딩 변수 : 리액트에서는 화면에서 수정이 일어났을때 정상적으로
// 보이게 만들어 주는 변수
// 사용법 : let [변수명, 수정함수] = useState("초기값")
let [element, setElement] = useState("안녕하세요");
// TODO: 2) myClick() 화살표 함수 : 안녕 으로 수정
// nfn
const myClick = () => {
// 수정 함수 : "안녕"
setElement("안녕");
};
return (
<div>
{element}
<br />
<button onClick={myClick}>문자열변경</button>
</div>
);
}
export default C_Exam;
결과
D ImportComp
css
/* D_ImportComp.css */
.dms01-h2 {
color: white;
background-color: black;
}
js
// D_ImportComp.js : 자식 컴포넌트
// TODO: 리액트 컴포넌트 디자인 적용하기 : css 파일 적용
// rfce
import React from 'react'
// css 파일 import
import "../assets/D_ImportComp.css";
function D_ImportComp() {
// TODO: 화면에 보이는 부분
return (
<div>
{/* class="" => className="" : 리액트에는 class 대신 사용함 */}
<h2 className="dms01-h2">ImportComp</h2>
</div>
)
}
export default D_ImportComp
결과
002
App.js
// 이미지 import
// import logo from './logo.svg';
// App.css import (기본 : 중앙정렬)
import './App.css';
import A_Lifecycle from './pages/A_Lifecycle';
import B_Props from "./pages/B_Props";
import C_Exam from "./pages/C_Exam";
import D_Exam2 from './pages/D_Exam2';
import E_Exam3 from './pages/E_Exam3';
import F_Clock from './pages/F_Clock';
// TODO: 리액트에서 처음으로 실행되는 js (최상위 부모 컴포넌트)
// TODO: 웹브라우저 확인(주소창) : http://localhost:3000
function App() {
// 변수/함수를 정의하는 부분
// 화면에 보이는 부분 : return 안에 있는 html 태그 화면에 보임
return (
<div className="App">
<h1>Start React 200!</h1>
{/* 자식 컴포넌트 추가 */}
{/* <A_Lifecycle></A_Lifecycle> */}
{/* <B_Props prop_value="hong gil dong"></B_Props> */}
{/* TODO: 연습문제 : 데이터 전달 */}
{/* <C_Exam prop_value="From App" /> */}
{/* 연습문제 2 */}
<D_Exam2 />
{/* 연습문제 3 */}
{/* <E_Exam3 name="처음 만난 파이썬"
numOfPage={300} /> */}
{/* <E_Exam3 name="처음 만난 자바"
numOfPage={500} /> */}
{/* <F_Clock /> */}
</div>
);
}
export default App;
D exam
// D_Exam2.js : 연습문제
// rfce
// TODO: 아래 생명주기 함수 2개를 만들어서 출력하세요
// TODO: 1) 화면이 뜰때 아래의 결과가 콘솔에 출력됨(console.log)
// TODO: 결과 : mount call
// TODO: 2) tmpState2 라는 변수의 값이(true) 변경되면 콘솔에 출력됨(console.log)
// TODO: 버튼을 클릭하면 변수의 값이 변경됨
// TODO: 결과 : false
import React, { useEffect, useState } from "react";
function D_Exam2() {
// TODO: 변수 (바인딩)
// 사용법 : let [변수명, set변수명] = useState(초기값);
let [tmpState2, setTmpState2] = useState(true);
// TODO: 1) 생명 주기 함수(생성) : 출력 : mount call
// TODO: 화면이 뜰때 자동 실행
// 사용법 : useEffect(()=>{실행문}, []);
useEffect(() => {
console.log("mount call");
}, []);
// TODO: 2) 생명 주기 함수(수정) : tmpState2 : true -> false (콘솔에 출력)
// 사용법 : useEffect(()=>{실행문}, [감시할변수명]);
useEffect(() => {
console.log(tmpState2); // 변수값 바뀌면 실행
}, [tmpState2]);
// TODO: 2-2) 클릭 이벤트 함수 정의
// 화살표 함수 단축키 : nfn
const handleClick = () => {
// 수정함수 : setter 함수 호출 : 값 변경 : true -> false
setTmpState2(false);
};
return (
<div>
<h2>[ THIS IS shouldComponentUpdate FUCNTION ]</h2>
<button onClick={handleClick}>클릭</button>
</div>
);
}
export default D_Exam2;
F Clock
// F_Clock.js : 자식
// rfce
import React from 'react'
function F_Clock() {
// 화면에 보이는 부분 : 아래 return
return (
<div>
<h1>안녕, 리액트</h1>
<h2>
현재 시간 :
{/* .toLocaleTimeString() : 국가별 현재 시간 출력 */}
{new Date().toLocaleTimeString()}
</h2>
</div>
)
}
export default F_Clock
결과
003
App.js
import A_Comment from "./pages/A_Comment";
import B_Comment_Exam from "./pages/B_Comment_Exam";
import C_Comment_Exam2 from "./pages/C_Comment_Exam2";
import D_CommentList from "./pages/D_CommentList";
import E_CommentList_Exam from "./pages/E_CommentList_Exam";
import F_CommentList_Exam2 from "./pages/F_CommentList_Exam2";
function App() {
return (
<div className="App">
{/* 자식 컴포넌트 추가 */}
<A_Comment />
{/* <B_Comment_Exam /> */}
{/* <C_Comment_Exam2 /> */}
{/* <D_CommentList /> */}
{/* <E_CommentList_Exam /> */}
{/* <F_CommentList_Exam2 /> */}
</div>
);
}
export default App;
style.css
.App {
text-align: center;
font-size: 50px;
}
Comment.css
.wrapper {
margin: 8;
padding: 8;
display: "flex";
flex-direction: "row";
border: "1px solid grey";
border-radius: 16;
};
.image {
width: 50;
height: 50;
border-radius: 25;
};
.contentContainer {
margin-left: 8;
display: "flex";
flex-direction: "column";
justify-content: "center";
};
.nameText {
color: "black";
font-size: 16;
font-weight: "bold";
};
.commentText {
color: "black";
font-size: 16;
};
A_Comment.js
// A_Comment.js : 자식
// rfce
import React from "react";
// Comment.css import
import "../assets/Comment.css";
import "../assets/styles.css";
import { useState } from "react";
function A_Comment() {
// TODO: 변수/함수 정의 : 여기
// 사용법 : let [변수, set변수] = useState(초기값);
// set변수 : setter 함수 (변수 값 저장 용도 함수)
// 화면 바인딩 용도 : useState() 함수 (훅(hook) 함수 : useXXX())
let [name, setName] = useState("홍길동");
let [comment, setComment] = useState("메모");
return (
<div className="wrapper">
<div className="imageContainer">
<img
className="image"
/>
</div>
<div className="contentContainer">
<span className="nameText">{name} </span>
<span className="commentText">{comment} </span>
</div>
</div>
);
}
export default A_Comment;
결과
C_Comment exam2.js
// C_Comment_Exam2.js : 자식(연습)
// rfce
import React, { useState } from 'react'
import "../assets/styles.css";
// TODO : useState 이용 4가지 변수 넣기, Comment_Exam2.css import
// name="제목"
// isUpdate=true
function C_Comment_Exam2() {
// 힌트 : 변수/함수 정의
let [img, setImg]
let [name, setName] = useState("제목");
let [isUpdate, setIsUpdate] = useState(true);
return (
<div className="wrapper">
{
// TODO : image 는 img 태그의 src 에 넣고, link 주소는 a href 속성에 넣어서 출력하시요
// TODO : isUpdate 가 true 이면 화면에 "true" 라고 출력하고, false 이면 "false"라고 출력하세요.
}
<div className="contentContainer">
<span className="commentText">
<img src={img} />{" "}
</span>
<br/>
<span className="nameText">{name} </span>
<span className="commentText">
<a href={link}>{link} </a>
</span>
<span className="commentText">{isUpdate? "true":"false"} </span>
</div>
</div>
)
}
export default C_Comment_Exam2
결과
D_CommentList.js
// D_CommentList.js : 자식
// TODO: 리액트의 반복문 : map() 함수 사용
// rfce
import React, {useState} from 'react'
import "../assets/styles.css";
function D_CommentList() {
// 객체배열 : [{},{} ...] === JSON 문서 데이터 형태(인터넷 통신 거의 표준)
// 프론트 <-(JSON 데이터)-> 벡엔트(DB 넣기)
const initialComments = [
{
name: "이인제",
comment: "안녕하세요, 소플입니다."
},
{
name: "유재석",
comment: "리액트, 재미있어요!!."
},
{
name: "강민경",
comment: "저도 리액트 배워보고 싶어요!!"
},
];
// TODO: 변수/함수 정의
// useState() 함수 이용 변수 정의
// 사용법 : let [변수명, set변수명] = useState(초기값)
let [comments, setComments] = useState(initialComments);
// HTML 태그 작성 부분 : return 부분
// 사용법 : 배열변수.map((value, index(생략), array(생략))=>{반복문;});
// value :배열의 값, index : 배열의 번호, array : 배열
// TODO: map() 함수 : 배열변수.map(함수());
// TODO: 용도 : for문 대신 사용하는 구문
// TODO: 특징 : 배열변수의 크기(길이, 건수)만큼 자동으로 반복함 (함수())
return (
<div>
{
comments.map((comment, index)=>{
// 반복문 : JSX 표현식(js + html 섞어 쓸수 있음)
return (
// TODO: 여기 : 반복 ?
<div className="wrapper" key={index}>
<div className="imageContainer">
<img
className="image"
/>
</div>
<div className="contentContainer">
<span className="nameText">{comment.name}</span>
<span className="commentText">{comment.comment}</span>
</div>
</div>
)
})
}
</div>
)
}
export default D_CommentList
결과
E_CommentList.exam
// CommentList_Exam.js
// TODO : 아래 데이터가 주어졌을때 화면에 출력하세요
import React, {useState} from "react";
import "../assets/styles.css";
function E_CommentList_Exam() {
// TODO : 아래 데이터가 주어졌을때 화면에 출력하세요
const initialComments = [
{
id: 1,
title: "어떻게 배울 것인가",
publisher: "비즈니스북스",
author: "존 맥스웰",
stock: 2,
},
{
id: 2,
title: "신경끄기의 기술",
publisher: "갤리온",
author: "마크 맨슨",
stock: 0,
},
{
id: 3,
title: "부의 미래",
publisher: "청림출판",
author: "앨빈 토플러",
stock: 5,
},
{
id: 4,
title: "기획자의 습관",
publisher: "홍익출판사",
author: "최장순",
stock: 4,
},
];
// 변수/함수 정의
// 사용법 : let [] = useState() : 바인딩 변수(객체배열 === 배열)
let [comments, setComments] = useState(initialComments);
// -------------------------
// html 태그
//
return (
<div>
{/* TODO :배열변수.map() 사용해서 반복문을
작성하세요 */}
{/* map 사용법 : 배열변수.map(()=>{return(태그)}) */}
{/* comment : 배열의 값, index : 배열의 인덱스번호 */}
{comments.map((comment, index) => {
// TODO: 반복 : 4번 , 자동반복
return (
// html 태그(반복)
<div>
<div>
<span>{comment.title}</span>
<span>{comment.publisher}</span>
<span>{comment.author}</span>
<span>{comment.stock}</span>
</div>
</div>
);
})}
</div>
);
}
export default E_CommentList_Exam;
결과
F_CommentList_Exam2
// CommentList_Exam2.js
// TODO : 연습문제 아래 데이터를 반복문으로
import React,{useState} from "react";
import "../assets/styles.css";
function F_CommentList_Exam2() {
// TODO : 연습문제 아래 데이터를 반복문으로
// 출력하세요
const initialWebtoons = [
{
name: "햄스터와 그녀",
isUpdate: true,
},
{
name: "프롬 스타",
isUpdate: true,
},
{
name: "위대한 로맨스",
isUpdate: false,
},
{
name: "빛나는 손을",
isUpdate: false,
},
];
// TODO: 변수 정의(useState())
let [webtoons, setWebtoons] = useState(initialWebtoons);
// 변수/함수 부분
// -----------------------------------
// html 부분
return (
<div>
{/* html 아래 내용 반복문 수행 */}
{/* 반복문 : 배열변수.map(()=>{return(태그)}) */}
{webtoons.map((webtoon, index) => {
return (
// html 태그 추가(반복)
<div className="wrapper" key={index}>
<div className="contentContainer">
<span className="commentText">
<img src={webtoon.img} />{" "}
</span>
<br/>
<span className="nameText">{webtoon.name}</span>
<span className="commentText">
<a href={webtoon.link}>{webtoon.link}</a>
</span>
<span className="commentText">
{webtoon.isUpdate? "true": "false"}
</span>
</div>
</div>
);
})}
</div>
);
}
export default F_CommentList_Exam2;
결과