리액트 시작 전 node.js 설치
https://nodejs.org/ko/
리액트 시작
npx create-react-app ~
cd ~
npm start
npm start를 하면서 엄청난 에러를 만났고
에러 구글 서치하고 몇십 분 동안 계속 찾아봤는데 안돼서
리액트 다시 시작을 했는데 너무 간단하게 돼서 좀 화가 났다
package.json
"scripts": {
"start": "react-scripts start", //개발모드 실행
"build": "react-scripts build", //실제 배포모드
"test": "react-scripts test", // 테스트
"eject": "react-scripts eject" //웹페이지, vavel설정 변경시 사용
},
component
리엑트로 만든 페이지는 컴포넌트들로 구성되어있음
페이지 단위로 html을 작성하는게 아니라
각 부분을 컴포넌트로 만들어서 조립해서 사용
비슷한 부분은 코드를 재사용할 수 있고 유지보수도 한결 쉬워짐
App.js
import './App.css';
function App() {
return (
<div className="App"></div>
);
}
export default App;
의 상태로 시작
함수로 만들어진 컴포넌트 = 함수형 컴포넌트
모든 컴포넌트는 대문자로 시작해야 함
import "./App.css";
function App() {
const name = "Tom";
const naver = {
name: "네이버",
url: "https://naver.com",
};
return (
<div className="App">
<h1 style={{ color: "#333", backgroundColor: "green" }}>
Hello, {name}.<p>{2 + 3}</p>
</h1>
<a href={naver.url}>{naver.name}</a>
</div>
);
}
export default App;
컴포넌트 만들기
src > component > Hello.js 파일 생성
export default function Hello() {
return <p>Hello</p>;
}
const Hello = () => {
<p>Hello</p>;
};
export default function Hello() {
return <p>Hello</p>;
}
App.js
import "./App.css";
import Hello from "./component(.js)/Hello";
(.js 빼고 적어도 됨)
function App() {
return (
<div className="App">
<Hello />
</div>
);
}
export default App;
welcome.js
export default function Welcome() {
return <h2>Welcome</h2>;
}
world.js
export default function World() {
return <h3>World!</h3>;
}
css
css 모듈 사용
(기존 Hello.css를 => Hello.module.css 로 변경)
import World from "./World";
import styles from "./Hello.module.css";
export default function Hello() {
return (
<div>
<h1>Hello</h1>
<World />
<div className={styles.box}>Hello</div>
</div>
);
}
이벤트
export default function Hello(){
function showName(){
console.log("cgok");
}
function(e){
console.log(e.target.value)
}
return(
<>
<button onClick={showName}>show name</button>
<button onClick={
()=>{
console.log(age)
}
}>show name</button>
<input type="text" onChange={showText}/>
</>
)
}
state
export default function Hello() {
let name = "cgok";
function changeName() {
name = name === "cgok" ? "chgk" : "cggo";
console.log(name);
document.getElementById("name").innerText = name;
}
return (
<div>
<h1>state</h1>
<h2 id="name">{name}</h2>
<button onClick={changeName}>Change</button>
</div>
);
}
props
App.js
import "./App.css";
import Hello from "./component/Hello";
function App(){
return (
<div className ="App">
<h3>props : properties</h3>
<Hello age={10}/>
<Hello age={20}/>
<Hello age={30}/>
</div>
);
}
export default App;
Hello.js
import { useState } from "react";
export default function Hello({ age }) {
const [name, setName] = useState('Mike');
const msg = age > 19 ? "성인 입니다. " : "미성년자 입니다.";
function changeName() {
const newName = name === "Mike" ? "Jane" : "Mike";
setName(newName)
}
return (
<>
<h2 id="name"> {name}({props.age}) : {msg} </h2> /
<button onClick = {changeNAme}>Change</button>
</>
)
}
dummy data
App.js
import "./App.css";
import DayList from "./component.js/DayList";
import Header from "./component.js/Header";
import Day from "./component.js/Day";
function App() {
return (
<div className="App">
<Header />
<DayList />
<Day />
</div>
);
}
export default App;
Day.js
import dummy from "../db/data.json";
export default function Day() {
//dummy.words
const day = 2;
const wordList = dummy.words.filter((word) => word.day === day);
console.log(wordList);
return (
<>
<table>
<tbody>
{wordList.map((word) => (
<tr key={word.id}>
<td>{word.eng}</td>
<td>{word.kor}</td>
</tr>
))}
</tbody>
</table>
</>
);
}
router 구현
npm install react-router-dom
import "./App.css";
import Day from "./component/Day";
import DayList from "./component/DayList";
import Header from "./component/Header";
import { BrowserRouter, Route, Routes } from "react-router-dom";
function App() {
return (
<BrowserRouter>
<div className="App">
<Header />
<Routes>
<Route path="/" element={<DayList />} />
<Route path="/day" element={<Day />} />
</Routes>
</div>
</BrowserRouter>
);
}
export default App;
//DayList.js
import { Link } from "react-router-dom";
import dummy from "../db/data.json";
export default function DayList() {
return (
<ul className="list_day">
{dummy.days.map((day) => (
<li key={day.id}>
<Link to={`/day/${day.day}`}>Day {day.day}</Link>
</li>
))}
</ul>
);
}
json-server
npm install -g json-server
json-server --watch ./src/db/data.json --port 3001
word.js
import { useState } from "react";
export default function Word({ word }) {
const [isShow, setIsShow] = useState(false);
const [isDone, setIsDone] = useState(word.isDone);
function toggleShow() {
setIsShow(!isShow);
}
function toggleDone() {
setIsDone(!isDone);
}
return (
<tr className={isDone ? "off" : ""}>
<td>
<input type="checkbox" checked={word.isDone} onChange={toggleDone} />
</td>
<td>{word.eng}</td>
<td>{isShow && word.kor}</td>
<td>
<button onClick={toggleShow}>뜻 {isShow ? "숨기기" : "보기"}</button>
<button className="btn_del">삭제</button>
</td>
</tr>
);
}
Day.js
import dummy from "../db/data.json";
import { useParams } from "react-router-dom";
import Word from "./Word ";
export default function Day() {
const a = useParams();
const day = a.day;
const wordList = dummy.words.filter((word) => word.day === Number(day));
return (
<>
<h2>Day {day}</h2>
<table>
<tbody>
{wordList.map((word) => (
<Word word={word} key={word.id} />
))}
</tbody>
</table>
</>
);
}
App.js
import "./App.css";
import DayList from "./component.js/DayList";
import Header from "./component.js/Header";
import Day from "./component.js/Day";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import EmptyPage from "./component.js/EmptyPage";
function App() {
return (
<BrowserRouter>
<div className="App">
<Header />
<Routes>
<Route path="/" element={<DayList />} />
<Route path="/day/:day" element={<Day />} />
<Route path="*" element={<EmptyPage />} />
</Routes>
</div>
</BrowserRouter>
);
}
export default App;
useEffect, fetch()
import { useEffect, useState } from "react";
import { Link } from "react-router-dom";
export default function DayList() {
const [days, setDays] = useState([]);
useEffect(() => {
fetch("http://localhost:3001/days")
.then((res) => {
return res.json();
})
.then((data) => {
setDays(data);
});
}, []);
return (
<>
<ul className="list_day">
{days.map((day) => (
<li key={day.id}>
<Link to={`/day/${day.day}`}>Day {day.day}</Link>
</li>
))}
</ul>
</>
);
}
커스텀 훅
DayList.js
import { Link } from "react-router-dom";
import useFetch from "../hooks/useFetch";
export default function DayList() {
const days = useFetch("http://localhost:3001/days");
return (
<ul className="list_day">
{days.map((day) => (
<li key={day.id}>
<Link to={`/day/${day.day}`}>Day {day.day}</Link>
</li>
))}
</ul>
);
}
Day.js
import { useParams } from "react-router-dom";
import useFetch from "../hooks/useFetch";
import Word from "./Word ";
export default function Day() {
const { day } = useParams();
const words = useFetch(`http://localhost:3001/words?day=${day}`);
return (
<>
<h2>Day {day}</h2>
<table>
<tbody>
{words.map((word) => (
<Word word={word} key={word.id} />
))}
</tbody>
</table>
</>
);
}
delete
function del() {
if (window.confirm("삭제 하시겠습니까?")) {
fetch(`http://localhost:3001/words/${word.id}`, {
method: "DELETE",
}).then((res) => {
if (res.ok) {
setWord({ id: 0 });
}
});
}
}
if (word.id === 0) {
return null;
}
return (
<tr className={isDone ? "off" : ""}>
<td>
<input type="checkbox" checked={isDone} onChange={toggleDone} />
</td>
<td>{word.eng}</td>
<td>{isShow && word.kor}</td>
<td>
<button onClick={toggleShow}>뜻 {isShow ? "숨기기" : "보기"}</button>
<button onClick={del} className="btn_del">
삭제
</button>
</td>
</tr>
);
}
로딩화면
DayList
import { Link } from "react-router-dom";
import useFetch from "../hooks/useFetch";
export default function DayList() {
const days = useFetch("http://localhost:3001/days");
if (days.length === 0) {
return <span>Loading...</span>;
}
return (
<ul className="list_day">
{days.map((day) => (
<li key={day.id}>
<Link to={`/day/${day.day}`}>Day {day.day}</Link>
</li>
))}
</ul>
);
}
Day.js
import { useParams } from "react-router-dom";
import useFetch from "../hooks/useFetch";
import Word from "./Word ";
export default function Day() {
const { day } = useParams();
const words = useFetch(`http://localhost:3001/words?day=${day}`);
return (
<>
<h2>Day {day}</h2>
{words.length === 0 && <span>Loading...</span>}
<table>
<tbody>
{words.map((word) => (
<Word word={word} key={word.id} />
))}
</tbody>
</table>
</>
);
}