- 1. ์ปดํฌ๋ํธ ์ ์ธ ๋ฐฉ์
- 2. Props ํ์ ์ ์
- 3. ์ํ(State) ํ์ ์ ์
- 4. ์ด๋ฒคํธ ํธ๋ค๋ฌ ํ์
- 5. styled-components ํ์
- 6. Redux ๊ด๋ จ ํ์ ์ ์
- 7. Firebase ๋ฐ์ดํฐ ํ์ ์ ์
- 8. ํ์ ๊ฐ๋ ์ถ๊ฐ
- 9. ์ธํฐํ์ด์ค ์ ์ ์ถ๊ฐ
- 10. ํ๊ฒฝ ๋ณ์ ํ์ ์ ์
- ์ฃผ์ ๊ฐ์ ํจ๊ณผ
1. ์ปดํฌ๋ํธ ์ ์ธ ๋ฐฉ์
// ๊ธฐ์กด JS
const Dashboard = () => {
// ...
}
// ๋ณํ๋ TSX
const Dashboard: React.FC = () => {
// ...
}
React.FC
(Function Component) ํ์ ์ ๋ช ์์ ์ผ๋ก ์ ์ธํ์ฌ TypeScript์๊ฒ ์ด ์ปดํฌ๋ํธ๊ฐ React ์ปดํฌ๋ํธ์์ ์๋ ค์ค๋ค- ์ด๋ ๊ฒ ํ๋ฉด ์ปดํฌ๋ํธ์ props ํ์ ์ ์๋์ผ๋ก ์ถ๋ก ํ ์ ์์ผ๋ฉฐ, React ๊ด๋ จ ํ์ ์ฒดํฌ๋ ๊ฐ๋ฅํ๋ค
- ์ต์ React์์๋
React.FC
๋์React.ComponentType
์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๋ ์๋ค
2. Props ํ์ ์ ์
// ๊ธฐ์กด JS
const CategoryEditor = ({ onClose }) => {
// ...
}
// ๋ณํ๋ TSX
interface CategoryEditorProps {
onClose: (value: boolean) => void;
}
const CategoryEditor: React.FC<CategoryEditorProps> = ({ onClose }) => {
// ...
}
interface
๋ฅผ ์ฌ์ฉํ์ฌ ์ปดํฌ๋ํธ์ props ํ์ ์ ๋ช ์์ ์ผ๋ก ์ ์ํ๋คonClose
ํจ์์ ๋งค๊ฐ๋ณ์์ ๋ฐํ ํ์ ์ ๋ช ํํ๊ฒ ์ง์ ํ ์ ์๋ค- ์ด๋ ๊ฒ ํ๋ฉด ์ปดํฌ๋ํธ ์ฌ์ฉ ์ ํ์ํ props๋ฅผ ๋๋ฝํ๊ฑฐ๋ ์๋ชป๋ ํ์ ์ ์ ๋ฌํ๋ ๊ฒ์ ๋ฐฉ์งํ ์ ์๋ค
3. ์ํ(State) ํ์ ์ ์
// ๊ธฐ์กด JS
const [course, setCourse] = useState(null);
// ๋ณํ๋ TSX
const [course, setCourse] = useState<Course | null>(null);
useState
ํ ์ ์ ๋ค๋ฆญ ํ์ ์ ์ฌ์ฉํ์ฌ ์ํ์ ํ์ ์ ๋ช ์ํ๋คCourse | null
์ course๊ฐ Course ํ์ ์ด๊ฑฐ๋ null์ผ ์ ์์์ ๋ํ๋ธ๋ค- ์ด๋ ๊ฒ ํ๋ฉด ์ํ๋ฅผ ์ฌ์ฉํ ๋ ํ์ ์์ ์ฑ์ด ๋ณด์ฅ๋๋ฉฐ, IDE์ ์๋์์ฑ ๊ธฐ๋ฅ๋ ํ์ฉํ ์ ์๋ค
4. ์ด๋ฒคํธ ํธ๋ค๋ฌ ํ์
// ๊ธฐ์กด JS
const handleSubmit = (e) => {
e.preventDefault();
// ...
}
// ๋ณํ๋ TSX
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
// ...
}
- ์ด๋ฒคํธ ํธ๋ค๋ฌ์ ๋งค๊ฐ๋ณ์์
React.FormEvent
ํ์ ์ ์ง์ ํ๋ค - ์ด๋ ํผ ์ ์ถ ์ด๋ฒคํธ์ ํ์ ์ ๋ช ํํ ํ์ฌ, ์ด๋ฒคํธ ๊ฐ์ฒด์ ์์ฑ์ ์์ ํ๊ฒ ์ ๊ทผํ ์ ์๊ฒ ํ๋ค
- ๋ค๋ฅธ ์ด๋ฒคํธ ํ์
์ผ๋ก๋
React.MouseEvent
,React.ChangeEvent
๋ฑ์ด ์๋ค
5. styled-components ํ์
// ๊ธฐ์กด JS
const Chip = styled.button`
background-color: ${props => props.active ? "#007bff" : "white"};
`
// ๋ณํ๋ TSX
const Chip = styled.button<{ active: boolean }>`
background-color: ${props => props.active ? "#007bff" : "white"};
`
- styled-components์์ props์ ํ์ ์ ์ ๋ค๋ฆญ์ผ๋ก ์ ์ํ๋ค
active
prop์ด boolean ํ์ ์์ ๋ช ์ํ์ฌ, ์ปดํฌ๋ํธ ์ฌ์ฉ ์ ํ์ ์ฒดํฌ๊ฐ ๊ฐ๋ฅํ๋ค- ์ด๋ ๊ฒ ํ๋ฉด ์คํ์ผ ์ปดํฌ๋ํธ์ props์ ๋ํ ํ์ ์์ ์ฑ์ด ๋ณด์ฅ๋๋ค
6. Redux ๊ด๋ จ ํ์ ์ ์
// ๊ธฐ์กด JS
const dispatch = useDispatch();
const { categories } = useSelector(state => state.category);
// ๋ณํ๋ TSX
const dispatch = useAppDispatch();
const { categories } = useAppSelector((state: RootState) => state.category);
- Redux์
dispatch
์useSelector
์ ํ์ ์ ์ถ๊ฐํ์ฌ ํ์ ์์ ์ฑ์ ๋ณด์ฅํ๋ค RootState
ํ์ ์ ์ฌ์ฉํ์ฌ ์ ์ฒด Redux ์ํ์ ๊ตฌ์กฐ๋ฅผ ๋ช ํํ ํ๋ค- ์ปค์คํ
ํ
์ธ
useAppDispatch
์useAppSelector
๋ฅผ ์ฌ์ฉํ์ฌ ํ์ ์ด ์ง์ ๋ dispatch์ selector๋ฅผ ์ ๊ณตํ๋ค
7. Firebase ๋ฐ์ดํฐ ํ์ ์ ์
// ๊ธฐ์กด JS
const coursesData = coursesSnapshot.docs.map(doc => ({
id: doc.id,
...doc.data()
}));
// ๋ณํ๋ TSX
const coursesData = coursesSnapshot.docs.map(doc => ({
id: doc.id,
...doc.data()
})) as Course[];
- Firebase์์ ๊ฐ์ ธ์จ ๋ฐ์ดํฐ์
Course
ํ์ ์ ๋ช ์์ ์ผ๋ก ์ง์ ํ๋ค as Course[]
๋ฅผ ์ฌ์ฉํ์ฌ ํ์ ๋จ์ธ(type assertion)์ ์ํํ๋ค- ์ด๋ ๊ฒ ํ๋ฉด Firebase ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ ๋ ํ์ ์์ ์ฑ์ด ๋ณด์ฅ๋๋ค
8. ํ์ ๊ฐ๋ ์ถ๊ฐ
// ๊ธฐ์กด JS
filtered = selectedCat.courseDetails.filter(course => course != null);
// ๋ณํ๋ TSX
filtered = (selectedCat.courseDetails || []).filter((course): course is Course => course !== null);
- ํ์
๊ฐ๋๋ฅผ ์ฌ์ฉํ์ฌ
null
์ด ์๋Course
๊ฐ์ฒด๋ง ํํฐ๋งํ๋ค course is Course
๋ ํ์ ๊ฐ๋๋ก, ํํฐ๋ง๋ ๋ฐฐ์ด์ดCourse[]
ํ์ ์์ ๋ณด์ฅํ๋ค- ์ด๋ ๊ฒ ํ๋ฉด
null
๊ฐ์ ์์ ํ๊ฒ ์ฒ๋ฆฌํ ์ ์๋ค
9. ์ธํฐํ์ด์ค ์ ์ ์ถ๊ฐ
export interface Course {
id: string;
courseName: string;
courseLength: number;
description: string;
locationInfo?: {
latitude: number;
longitude: number;
};
}
export interface Category {
id: string;
title: string;
courseIdList: string[];
courseDetails?: (Course | null)[];
}
- ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ฌ์ฉ๋๋ ์ฃผ์ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ์ธํฐํ์ด์ค๋ก ์ ์ํ๋ค
?
๋ฅผ ์ฌ์ฉํ์ฌ ์ ํ์ ์์ฑ์ ํ์ํ๋ค- ์ธํฐํ์ด์ค๋ฅผ exportํ์ฌ ๋ค๋ฅธ ํ์ผ์์ ์ฌ์ฌ์ฉํ ์ ์๊ฒ ํ๋ค
10. ํ๊ฒฝ ๋ณ์ ํ์ ์ ์
// ๊ธฐ์กด JS
process.env.REACT_APP_FIREBASE_API_KEY
// ๋ณํ๋ TSX
declare global {
namespace NodeJS {
interface ProcessEnv {
REACT_APP_FIREBASE_API_KEY: string;
// ... ๋ค๋ฅธ ํ๊ฒฝ ๋ณ์๋ค
}
}
}
ProcessEnv
์ธํฐํ์ด์ค๋ฅผ ํ์ฅํ์ฌ ํ๊ฒฝ ๋ณ์์ ํ์ ์ ์ ์ํ๋ค- ์ด๋ ๊ฒ ํ๋ฉด ํ๊ฒฝ ๋ณ์๋ฅผ ์ฌ์ฉํ ๋ ํ์ ์ฒดํฌ๊ฐ ๊ฐ๋ฅํ๋ค
- ํ์ ํ๊ฒฝ ๋ณ์๊ฐ ๋๋ฝ๋์์ ๋ ์ปดํ์ผ ์์ ์ ์ค๋ฅ๋ฅผ ๋ฐ๊ฒฌํ ์ ์๋ค
์ฃผ์ ๊ฐ์ ํจ๊ณผ
- ํ์
์์ ์ฑ ํฅ์
- ์ปดํ์ผ ์์ ์ ํ์ ๊ด๋ จ ์ค๋ฅ๋ฅผ ๋ฐ๊ฒฌํ ์ ์๋ค
- ๋ฐํ์ ์๋ฌ๋ฅผ ์ค์ผ ์ ์๋ค
- ์ฝ๋ ์๋์์ฑ ์ง์
- IDE์์ ๋ ์ ํํ ์๋์์ฑ์ ์ ๊ณตํ๋ค
- ์ฝ๋ ์์ฑ ์๋๊ฐ ํฅ์๋๋ค
- ์ค์ ๋ฐฉ์ง
- ํ์ props ๋๋ฝ์ ๋ฐฉ์งํ๋ค
- ์๋ชป๋ ํ์ ์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ๋ ๊ฒ์ ๋ฐฉ์งํ๋ค
- ์ฝ๋ ๊ฐ๋
์ฑ ํฅ์
- ํ์ ์ ์๋ฅผ ํตํด ์ฝ๋์ ์๋๋ฅผ ๋ช ํํ ํ ์ ์๋ค
- ๋ค๋ฅธ ๊ฐ๋ฐ์๊ฐ ์ฝ๋๋ฅผ ์ดํดํ๊ธฐ ์ฌ์์ง๋ค
- ๋ฆฌํฉํ ๋ง ์ ์์ ์ฑ ํฅ์
- ํ์ ์์คํ ์ ํตํด ๋ฆฌํฉํ ๋ง ์ ๋ฐ์ํ ์ ์๋ ์ค๋ฅ๋ฅผ ๋ฏธ๋ฆฌ ๋ฐ๊ฒฌํ ์ ์๋ค
- ์ฝ๋ ๋ณ๊ฒฝ ์ ์ํฅ ๋ฒ์๋ฅผ ํ์ ํ๊ธฐ ์ฌ์์ง๋ค
- ๋ฐํ์ ์๋ฌ ์ฌ์ ๋ฐฉ์ง
- ํ์ ์ฒดํฌ๋ฅผ ํตํด ๋ฐํ์์ ๋ฐ์ํ ์ ์๋ ์ค๋ฅ๋ฅผ ๋ฏธ๋ฆฌ ๋ฐฉ์งํ ์ ์๋ค
- ๋๋ฒ๊น ์๊ฐ์ ์ค์ผ ์ ์๋ค
์ด๋ฌํ ๋ณ๊ฒฝ์ฌํญ๋ค๋ก ์ธํด ์ฝ๋์ ํ์ง๊ณผ ์ ์ง๋ณด์์ฑ์ด ํฌ๊ฒ ํฅ์๋๋ค!
๋ฐ์ํ
'๐ค Web > ๐ React' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๐ Styled Components๋ก ๋ผ์ดํธ/๋คํฌ ๋ชจ๋ ์ ํํ๊ธฐ (0) | 2025.03.26 |
---|---|
Styled Components - ์ ๋๋ฉ์ด์ , ์ปดํฌ๋ํธ ์ ํ์, ์ค์ฒฉ ์คํ์ผ๋ง (0) | 2025.03.26 |
Styled Component์์ ์ปดํฌ๋ํธ ํ์ฅํ๊ธฐ (0) | 2025.03.26 |
๋ฆฌ์กํธ ํด๋๊ตฌ์กฐ์ ์ ์์ด ์์๊น (0) | 2023.02.17 |
๊ฐ๋ฐ์๋๊ตฌ ์ผ๋ฌด์ฅ๊ฒ ์ฐ๊ธฐ (0) | 2023.02.17 |
๋๊ธ