├── [8장] JSX에서 TSX로
└── practice-8-2
│ ├── src
│ ├── react-app-env.d.ts
│ ├── App.tsx
│ ├── index.tsx
│ ├── styles
│ │ ├── Theme.styles.ts
│ │ └── Select.styles.ts
│ └── components
│ │ ├── FruitSelect.tsx
│ │ └── Select.tsx
│ ├── .gitignore
│ ├── public
│ └── index.html
│ ├── tsconfig.json
│ ├── package.json
│ └── README.md
├── assets
├── 맹구.jpg
├── 유리.jpg
├── 짱구.jpg
├── 철수.jpg
├── 원장님.jpg
└── woowa-ts-book.jpg
├── .github
├── .GITHUB_MESSAGE_TEMPLATE.txt
└── ISSUE_TEMPLATE
│ └── ❓-질문-템플릿.md
├── [11장] CSS-in-JS
└── 이예솔.md
├── README.md
├── [6장] 타입스크립트 컴파일
└── 이에스더.md
├── [13장] 타입스크립트와 객체 지향
└── 강지윤.md
├── [12장] 타입스크립트 프로젝트 관리
└── 이성령.md
├── [9장] 훅
└── 이성령.md
├── [10장] 상태관리
└── 이예솔.md
├── [7장] 비동기 호출
└── 이예솔.md
├── [4장] 타입 확장하기·좁히기
└── 강지윤.md
├── [5장] 타입 활용하기
└── 이성령.md
├── [3장] 고급 타입
└── 이예솔.md
└── [2장] 타입
└── 이에스더.md
/[8장] JSX에서 TSX로/practice-8-2/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/assets/맹구.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Coding-Village-Protector/woowahan-ts/HEAD/assets/맹구.jpg
--------------------------------------------------------------------------------
/assets/유리.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Coding-Village-Protector/woowahan-ts/HEAD/assets/유리.jpg
--------------------------------------------------------------------------------
/assets/짱구.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Coding-Village-Protector/woowahan-ts/HEAD/assets/짱구.jpg
--------------------------------------------------------------------------------
/assets/철수.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Coding-Village-Protector/woowahan-ts/HEAD/assets/철수.jpg
--------------------------------------------------------------------------------
/assets/원장님.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Coding-Village-Protector/woowahan-ts/HEAD/assets/원장님.jpg
--------------------------------------------------------------------------------
/assets/woowa-ts-book.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Coding-Village-Protector/woowahan-ts/HEAD/assets/woowa-ts-book.jpg
--------------------------------------------------------------------------------
/[8장] JSX에서 TSX로/practice-8-2/src/App.tsx:
--------------------------------------------------------------------------------
1 | import FruitSelect from "./components/FruitSelect";
2 |
3 | function App() {
4 | return (
5 | <>
6 |
과일고르기🍎🍌🍇
7 |
8 | >
9 | );
10 | }
11 |
12 | export default App;
13 |
--------------------------------------------------------------------------------
/.github/.GITHUB_MESSAGE_TEMPLATE.txt:
--------------------------------------------------------------------------------
1 | 📚: [?장] ?챕터명? - ?이름?
2 |
3 | 또는
4 |
5 | 📜: ?문서수정?
6 | # ex) 📚: [2장] 타입 - 이성령
7 | # ex) 📜: README 수정
8 | # ------------------------------
9 | # 커밋 메세지 적용 방법
10 | # $ git config --global core.editor "code --wait" # 기본에디터로 VScode 지정
11 | # $ git config commit.template .github/.GITHUB_MESSAGE_TEMPLATE.txt
--------------------------------------------------------------------------------
/[8장] JSX에서 TSX로/practice-8-2/src/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom/client";
3 | import App from "./App";
4 |
5 | const root = ReactDOM.createRoot(
6 | document.getElementById("root") as HTMLElement
7 | );
8 | root.render(
9 |
10 |
11 |
12 | );
13 |
--------------------------------------------------------------------------------
/[8장] JSX에서 TSX로/practice-8-2/src/styles/Theme.styles.ts:
--------------------------------------------------------------------------------
1 | export const theme = {
2 | fontSize: {
3 | default: "16px",
4 | small: "14px",
5 | large: "18px",
6 | },
7 | color: {
8 | white: "#FFFFFF",
9 | black: "#000000",
10 | orange: "#F58F00",
11 | },
12 | };
13 |
14 | export type Theme = typeof theme;
15 | export type FontSize = keyof Theme["fontSize"];
16 | export type Color = keyof Theme["color"];
17 |
--------------------------------------------------------------------------------
/[8장] JSX에서 TSX로/practice-8-2/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/[8장] JSX에서 TSX로/practice-8-2/src/styles/Select.styles.ts:
--------------------------------------------------------------------------------
1 | import { styled } from "styled-components";
2 | import { Color, FontSize, theme } from "./Theme.styles";
3 |
4 | export interface SelectStyleProps {
5 | color: Color;
6 | fontSize: FontSize;
7 | }
8 |
9 | export const StyledSelect = styled.select`
10 | color: ${({ color }) => theme.color[color]};
11 | font-size: ${({ fontSize }) => theme.fontSize[fontSize]};
12 | `;
13 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/❓-질문-템플릿.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "❓ 질문 템플릿"
3 | about: 궁금한 점을 질문해주세요.
4 | title: 0.0.0_질문
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 |
20 |
21 | 📝 p
22 |
23 | ❓ 질문
24 |
--------------------------------------------------------------------------------
/[8장] JSX에서 TSX로/practice-8-2/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 8.2 타입스크립트로 리액트 컴포넌트 만들기
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/[8장] JSX에서 TSX로/practice-8-2/src/components/FruitSelect.tsx:
--------------------------------------------------------------------------------
1 | import { FC, useState } from "react";
2 | import Select from "./Select";
3 |
4 | type Fruit = keyof typeof fruits; // 'apple' | 'banana' | 'blueberry';
5 |
6 | const fruits = { apple: "사과", banana: "바나나", blueberry: "블루베리" };
7 |
8 | const FruitSelect: FC = () => {
9 | const [fruit, changeFruit] = useState("apple");
10 | return (
11 | <>
12 |
13 | 지금 고른 과일은 {fruit}야
14 | >
15 | );
16 | };
17 |
18 | export default FruitSelect;
19 |
--------------------------------------------------------------------------------
/[8장] JSX에서 TSX로/practice-8-2/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es6",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "esModuleInterop": true,
8 | "allowSyntheticDefaultImports": true,
9 | "strict": true,
10 | "forceConsistentCasingInFileNames": true,
11 | "noFallthroughCasesInSwitch": true,
12 | "module": "esnext",
13 | "moduleResolution": "node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true,
17 | "jsx": "react-jsx"
18 | },
19 | "include": ["src"]
20 | }
21 |
--------------------------------------------------------------------------------
/[8장] JSX에서 TSX로/practice-8-2/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "practice-8-2",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.17.0",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "@types/jest": "^27.5.2",
10 | "@types/node": "^16.18.76",
11 | "@types/react": "^18.2.48",
12 | "@types/react-dom": "^18.2.18",
13 | "react": "^18.2.0",
14 | "react-dom": "^18.2.0",
15 | "react-scripts": "5.0.1",
16 | "styled-components": "^6.1.8",
17 | "typescript": "^4.9.5",
18 | "web-vitals": "^2.1.4"
19 | },
20 | "scripts": {
21 | "start": "react-scripts start",
22 | "build": "react-scripts build",
23 | "test": "react-scripts test",
24 | "eject": "react-scripts eject"
25 | },
26 | "eslintConfig": {
27 | "extends": [
28 | "react-app",
29 | "react-app/jest"
30 | ]
31 | },
32 | "browserslist": {
33 | "production": [
34 | ">0.2%",
35 | "not dead",
36 | "not op_mini all"
37 | ],
38 | "development": [
39 | "last 1 chrome version",
40 | "last 1 firefox version",
41 | "last 1 safari version"
42 | ]
43 | },
44 | "devDependencies": {
45 | "@types/styled-components": "^5.1.34"
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/[8장] JSX에서 TSX로/practice-8-2/src/components/Select.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * Select 컴포넌트
3 | * @param {Object} props - Select 컴포넌트로 넘겨주는 속성
4 | * @param {Object} props.options - { [key: string]: string } 형식으로 이루어진 option 객체
5 | * @param {string | undefined} props.selectedOption - 현재 선택된 option의 key값 (optional)
6 | * @param {function} props.onChange - select 값이 변경되었을 때 불리는 callBack 함수 (optional)
7 | * @returns {JSX.Element}
8 | */
9 |
10 | import { SelectStyleProps, StyledSelect } from "../styles/Select.styles";
11 |
12 | type ReactSelectProps = React.ComponentPropsWithoutRef<"select">;
13 |
14 | interface SelectProps>
15 | extends Pick,
16 | Partial {
17 | options: OptionType;
18 | selectedOption?: keyof OptionType;
19 | onChange?: (selected?: keyof OptionType) => void;
20 | }
21 |
22 | const Select = >({
23 | options,
24 | selectedOption,
25 | onChange,
26 | fontSize = "default",
27 | color = "orange",
28 | }: SelectProps) => {
29 | const handleChange: React.ChangeEventHandler = (e) => {
30 | const selected = Object.entries(options).find(
31 | ([_, value]) => value === e.target.value
32 | )?.[0];
33 | onChange?.(selected);
34 | };
35 |
36 | return (
37 |
43 | {Object.entries(options).map(([key, value]) => (
44 |
47 | ))}
48 |
49 | );
50 | };
51 |
52 | export default Select;
53 |
--------------------------------------------------------------------------------
/[8장] JSX에서 TSX로/practice-8-2/README.md:
--------------------------------------------------------------------------------
1 | # Getting Started with Create React App
2 |
3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
4 |
5 | ## Available Scripts
6 |
7 | In the project directory, you can run:
8 |
9 | ### `npm start`
10 |
11 | Runs the app in the development mode.\
12 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
13 |
14 | The page will reload if you make edits.\
15 | You will also see any lint errors in the console.
16 |
17 | ### `npm test`
18 |
19 | Launches the test runner in the interactive watch mode.\
20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
21 |
22 | ### `npm run build`
23 |
24 | Builds the app for production to the `build` folder.\
25 | It correctly bundles React in production mode and optimizes the build for the best performance.
26 |
27 | The build is minified and the filenames include the hashes.\
28 | Your app is ready to be deployed!
29 |
30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
31 |
32 | ### `npm run eject`
33 |
34 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!**
35 |
36 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
37 |
38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
39 |
40 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
41 |
42 | ## Learn More
43 |
44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
45 |
46 | To learn React, check out the [React documentation](https://reactjs.org/).
47 |
--------------------------------------------------------------------------------
/[11장] CSS-in-JS/이예솔.md:
--------------------------------------------------------------------------------
1 | # 11장 CSS-in-JS
2 |
3 | ## 11.1 CSS-in-JS란
4 |
5 | ### 1) CSS-in-JS와 인라인 스타일의 차이
6 |
7 | CSS-in-JS는 CSS-in-CSS보다 더 강력한 추상화 수준을 제공한다. CSS-in-JS를 통해 자바스크립트 사용하여 스타일을 선언적이고 유지보수할 수 있는 방식으로 표현할 수 있다.
8 |
9 | > **인라인스타일**: HTML 요소 내부에 직접 스타일을 적용하는 방식, HTML 태그의 `style` 속성을 사용하여 인라인 스타일을 적용할 수 있다.
10 |
11 | 인라인 스타일의 예시와 DOM 노드 연결 방식이다.
12 |
13 | ```tsx
14 | const textStyles = {
15 | color: 'white',
16 | backgroundColor: 'black',
17 | };
18 |
19 | const SomeComponent = () => {
20 | return inline style!
;
21 | };
22 | ```
23 |
24 | ```tsx
25 | inline style!
26 | ```
27 |
28 | 인라인은 DOM노드에 속성으로 스타일을 추가했다.
29 |
30 | CSS-in-JS 예시와 DOM 노드 연결 방식이다.
31 |
32 | ```tsx
33 | import styled from 'styled-components';
34 |
35 | const Text = styled.div`
36 | color: white;
37 | background: black;
38 | `;
39 |
40 | // 다음처럼 사용
41 | const Example = () => Hello CSS-in-JS;
42 | ```
43 |
44 | ```tsx
45 |
51 |
52 | Hello CSS-in-JS
53 | ```
54 |
55 | CSS-in-JS는 DOM 상단에 `