강의 들으면서 복습겸 적은거라 나중에 따로 정리를 다시 하던가 해야겠다.
프로젝트 생성
npx create-react-app [프로젝트명]
프로젝트 실행
npm start // http://localhost:3000
- HMR(Hot Module Replacement) : 코드 수정 시 화면에 바로 반영
Component
함수형 컴포넌트
JSX(JavaScript XML)
스타일은 객체 형태로 전달해야 적용이 된다. 카멜케이스로 작성
중괄호({ }) 내부에서 변수 사용 가능
재사용에 용이
import Hello from "./component/Hello";
function App() {
const name = "Tom";
const naver = {
name: "네이버",
url: "https://naver.com",
};
return (
<div className="App">
<h1
style={{
color: 'skyblue',
backgroundColor: 'blue',
}}
>
Hi, {name}
</h1>
<a href={naver.url}>{naver.name}</a>
<Hello />
</div>
);
}
/component/Hello.js
export default function Hello() {
<p>Hello</p>;
}
.css 파일은 각 컴포넌트에 종속되는 것이 아니라 head에 들어가므로 같은 className을 가지고 있으면 오버라이드 된다.
컴포넌트에 특화된 css 파일은 [컴포넌트명].module.css 명칭이 기본
styles 객체 생성 후 className에 지정
global 단위가 아니라 컴포넌트 단위로 관리가 되는 것이 장점
import styles from "./Hello.module.css";
<div className={styles.box}>Hello</div>
이벤트
function showName() {
console.log("Mike");
}
function showAge(age) {
console.log(age);
}
function showText(e) {
console.log(e.target.value);
}
// ...
<button onClick={showName}>Show name</button>
<button
onClick={() => {
showAge(10);
}}
>
Show age
<input type="text" onChange={showText} />
</button>
json-server
json-server는 안써본거라서 강의만 보다가 다시 작성..
npm install -g json-server
# json-server --watch [데이터 파일 경로] --port [원하는 포트번호]
json-server --watch ./src/db/data.json --port 3001
REST API
- Create : POST
- Read : GET
- Update : PUT
- Delete : DELETE
여기서 수정되는 내용들은 모두 data.json에 반영이 된다.
GET
import { useEffect, useState } from "react";
import { Link } from "react-router-dom";
export default function DayList() {
const [days, setDays] = useState([]);
const [count, setCount] = useState(0);
function onClick() {
setCount(count + 1);
}
function onClick2() {
setDays([
...days,
{
id: Math.random(),
day: 1
}
]);
}
useEffect(() => {
fetch('http://localhost:3001/days') // 비동기. url filter는 ?xx=${yyy}
.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 {days.day}</Link>
</li>
))}
</ul>
<button onClick={onClick}>{count}</button>
</>
);
}
PUT, DELETE
function toggleDone() {
fetch(`http://localhost:3001/words/{word.id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
...word,
isDone: !isDone
}),
})
.then(res => {
if(res.ok) {
setIsDone(!isDone);
}
});
}
function del() {
if(window.confirm('삭제하시겠습니까?')) {
fetch(`http://localhost:3001/words/{word.id}`, {
method: 'DELETE',
}).then(res => {
if(res.ok) {
setWord({ id: 0 });
}
});
}
}
POST
function onSubmit(e) {
e.preventDefault();
console.log(engRef.current.value);
fetch(`http://localhost:3001/words/{word.id}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
day : dayRef.current.value,
eng : engRef.current.value,
kor : korRef.current.value,
isDone : false
}),
})
.then(res => {
if(res.ok) {
alert("생성이 완료 되었습니다.");
history.push(`/day/${dayRef.current.value}`);
}
});
}
const engRef = useRef(null);
<input type="text" placeholder="" ref={engRef} />
Custom Hooks
/src/hooks/useFetch.js
import {useEffect, useState } from "react";
export default function useFetch(url) {
const [data, setData] = useState([]);
useEffect(() => {
fetch(url)
.then(res => {
return res.json()
})
.then(data => {
setData([data]);
})
}, [url]);
return data;
}
const days = useFetch(`http://localhost:3001/words?day=${day}`);
데이터가 뜨는 시간이 느리다면 이렇게 처리해 주는 것도 좋은 방법
{words.length === 0 && <span>Loading...</span>}
데이터 저장 시 버튼을 여러번 누르지 못하게 처리하는 것
const [isLoading, setIsLoading] = useState(false);
function onSubmit(e) {
...
if (!isLoading) {
setIsLoading(true);
...
.then(res => {
setIsLoading(false);
...
}
<button
style={{
opacity: isLoading ? 0.3 : 1
}}
>
{isLoading ? "Saving..." : "저장"}
</button>
타입스크립트 적용하기
npm install typescript @types/node @types/react @types/react-dom @types/jest @types/react-router-dom
.js → .ts, .jsx → .tsx로 변경
interface IProps {
word: IWord
}
export interface IWord {
day: string;
eng: string;
kor: string;
isDone; boolean;
id: number;
}
export default function Word({ word; w }: IProps) {
...
});
setWord({...word, id: 0, });
const { day } useParams<{ day:string }>(); // <> : 제네릭
const words : IWord[] = useFetch(`http://localhost:3001/words?day=${day}`);
const engRef = useRef<HTMLInputElement>(null);
function onSubmit(e: React.FormEvent) {
'개발 > FE' 카테고리의 다른 글
Monorepo vs. Multirepo: 코드 관리 방식 비교 (0) | 2024.11.19 |
---|---|
npm vs. pnpm : 패키지 매니저 비교 (0) | 2024.11.19 |
프론트엔드 아키텍처, 방법론, 디자인 패턴 (0) | 2024.11.02 |
styled-component의 ThemeProvider (0) | 2024.10.28 |
본격적인 공부에 앞서 프론트엔드 복습하기 (2) | 2024.10.05 |