Skip to content

Commit

Permalink
TS 마이그레이션
Browse files Browse the repository at this point in the history
  • Loading branch information
yammyam committed Jun 28, 2024
1 parent 08bcb73 commit e34e5ed
Show file tree
Hide file tree
Showing 18 changed files with 1,241 additions and 342 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ dist-ssr
*.njsproj
*.sln
*.sw?
.vercel
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
1,361 changes: 1,057 additions & 304 deletions package-lock.json

Large diffs are not rendered by default.

11 changes: 7 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,25 @@
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
"build": "tsc && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/react": "^18.2.66",
"@types/react-dom": "^18.2.22",
"@types/jest": "^29.5.12",
"@types/node": "^20.14.9",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react": "^4.2.1",
"eslint": "^8.57.0",
"eslint-plugin-react": "^7.34.1",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.6",
"typescript": "^5.5.2",
"vite": "^5.2.0"
}
}
26 changes: 20 additions & 6 deletions src/App.jsx → src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,15 @@ import {
import Header from "./components/Header";
import Editor from "./components/Editor";
import List from "./components/List";
import { Todo } from "./types";

function reducer(state, action) {
type Action =
| { type: "INIT"; data: Todo[] }
| { type: "CREATE"; data: Todo }
| { type: "UPDATE"; targetId: number }
| { type: "DELETE"; targetId: number };

function reducer(state: Todo[], action: Action): Todo[] {
let nextState;

switch (action.type) {
Expand All @@ -38,8 +45,15 @@ function reducer(state, action) {
return nextState;
}

export const TodoStateContext = createContext();
export const TodoDispatchContext = createContext();
export const TodoStateContext = createContext<Todo[] | undefined>(undefined);
export const TodoDispatchContext = createContext<
| {
onCreate: (content: string) => void;
onUpdate: (targetId: number) => void;
onDelete: (targetId: number) => void;
}
| undefined
>(undefined);

function App() {
const [isLoading, setIsLoading] = useState(true);
Expand Down Expand Up @@ -67,7 +81,7 @@ function App() {
setIsLoading(false);
}, []);

const onCreate = useCallback((content) => {
const onCreate = useCallback((content: string) => {
dispatch({
type: "CREATE",
data: {
Expand All @@ -79,7 +93,7 @@ function App() {
});
}, []);

const onUpdate = useCallback((targetId) => {
const onUpdate = useCallback((targetId: number) => {
// todos State값들 중에
// targetId와 일치하는 id를 갖는 투두 아이템의 isDone 변경
dispatch({
Expand All @@ -88,7 +102,7 @@ function App() {
});
}, []);

const onDelete = useCallback((targetId) => {
const onDelete = useCallback((targetId: number) => {
dispatch({
type: "DELETE",
targetId: targetId,
Expand Down
28 changes: 20 additions & 8 deletions src/components/Editor.jsx → src/components/Editor.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,38 @@
import "./Editor.css";
import { useState, useRef, useContext } from "react";
import {
useState,
useRef,
useContext,
ChangeEvent,
KeyboardEvent,
RefObject,
} from "react";
import { TodoDispatchContext } from "../App";

const Editor = () => {
const { onCreate } = useContext(TodoDispatchContext);

const [content, setContent] = useState("");
const ref = useRef();
const onChangeContent = (e) => {
const context = useContext(TodoDispatchContext);
if (!context) {
throw new Error(
"TodoDispatchContext must be used within a TodoDispatchProvider"
);
}
const { onCreate } = context;
const [content, setContent] = useState<string>("");
const ref = useRef<HTMLInputElement>(null);
const onChangeContent = (e: ChangeEvent<HTMLInputElement>) => {
setContent(e.target.value);
};

const onSubmit = () => {
if (content === "") {
ref.current.focus();
ref.current?.focus();
return;
}
onCreate(content);
setContent("");
};

const onKeydown = (e) => {
const onKeydown = (e: KeyboardEvent<HTMLInputElement>) => {
if (e.keyCode === 13) {
onSubmit();
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/Header.jsx → src/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import "./Header.css";
import { memo } from "react";

const Header = () => {
const Header: React.FC = () => {
return (
<div className="Header">
<h3>오늘의 할 일🐿️</h3>
Expand Down
14 changes: 10 additions & 4 deletions src/components/List.jsx → src/components/List.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
import "./List.css";
import TodoItem from "./TodoItem";
import { useState, useMemo, useContext } from "react";
import { useState, useMemo, useContext, ChangeEvent } from "react";
import { TodoStateContext } from "../App";
import { Todo } from "../types";

const List = () => {
const todos = useContext(TodoStateContext);
// 원래 객체로 todos를 뭉쳐서 가져와서 구조분해 할당을 했지만 props로 todos 자체를 보내고있어서 todos는 배열임
// console.log(Array.isArray(todos)); ==> true
const [search, setSearch] = useState("");
const onChangeSearch = (e) => {

if (!todos) {
throw new Error("TodoStateContext must be used within a TodoStateProvider");
}
const [search, setSearch] = useState<string>("");

const onChangeSearch = (e: ChangeEvent<HTMLInputElement>) => {
setSearch(e.target.value);
};

const getFilteredDate = () => {
const getFilteredDate = (): Todo[] => {
if (search === "") {
return todos;
}
Expand Down
15 changes: 13 additions & 2 deletions src/components/TodoItem.jsx → src/components/TodoItem.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
import "./TodoItem.css";
import { memo, useContext } from "react";
import { TodoDispatchContext } from "../App";
const TodoItem = ({ id, isDone, content, date }) => {
const { onUpdate, onDelete } = useContext(TodoDispatchContext);
import { Todo } from "../types";

interface TodoItemProps extends Todo {}
const TodoItem: React.FC<TodoItemProps> = ({ id, isDone, content, date }) => {
const context = useContext(TodoDispatchContext);

if (!context) {
throw new Error(
"TodoDispatchContext must be used within a TodoDispatchProvider"
);
}

const { onUpdate, onDelete } = context;
const onChangeCheckbox = () => {
onUpdate(id);
};
Expand Down
5 changes: 0 additions & 5 deletions src/main.jsx

This file was deleted.

7 changes: 7 additions & 0 deletions src/main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import ReactDOM from "react-dom/client";
import App from "./App";
import "./index.css";

ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
<App />
);
6 changes: 6 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface Todo {
id: number;
isDone: boolean;
content: string;
date: number;
}
27 changes: 27 additions & 0 deletions tsconfig.app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"compilerOptions": {
"composite": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,

/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",

/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"]
}
29 changes: 29 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["DOM", "DOM.Iterable", "ES2020"],
"module": "ESNext",
"skipLibCheck": true,
//
"moduleResolution": "Bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
//
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
//
"allowJs": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src"],
"exclude": ["node_modules"],
"references": [{ "path": "./tsconfig.node.json" }]
}
11 changes: 11 additions & 0 deletions tsconfig.node.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"composite": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true,
"strict": true
},
"include": ["vite.config.ts"]
}
1 change: 1 addition & 0 deletions vite-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// <reference types="vite/client"/>
7 changes: 0 additions & 7 deletions vite.config.js

This file was deleted.

30 changes: 30 additions & 0 deletions vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import path from "path";
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
plugins: [react()],
server: {
host: "localhost",
port: 3000,
open: true,
},
resolve: {
alias: {
// TypeScript 파일 확장자 추가
"/@/": path.resolve(__dirname, "src/"),
},
extensions: [".tsx", ".ts", ".jsx", ".js"],
},
build: {
outDir: "dist",
emptyOutDir: true,
minify: true,
sourcemap: true,
rollupOptions: {
input: {
main: path.resolve(__dirname, "./src/main.tsx"), // entry 파일 경로 지정
},
},
},
});

0 comments on commit e34e5ed

Please sign in to comment.