Skip to content

Udemy/Ts/React-Extra-1: Zod #65

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: Udemy/Ts/React-Extra-r
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"fp-ts": "^2.16.9",
"io-ts": "^2.2.21",
"react": "^18.3.1",
"react-dom": "^18.3.1"
"react-dom": "^18.3.1",
"zod": "^3.23.8"
},
"devDependencies": {
"@eslint/js": "^9.9.0",
Expand Down
42 changes: 14 additions & 28 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,26 @@
import { useState, useEffect } from "react";
import reactLogo from "./assets/react.svg";
import viteLogo from "/vite.svg";
import { useEffect } from "react";
// import reactLogo from "./assets/react.svg";
// import viteLogo from "/vite.svg";
import "./App.css";
import { validateData } from "./test"; // test.ts 파일을 import
// import ButtonComponents from "./shared/components/button.components"; //원문 파일
import ButtonComponents from "./shared/components/Button.components.test"; //Test 파일로 대체
import { validateData } from "./test"; // test.ts 파일을

function App() {
const [count, setCount] = useState(0);
const Button = ButtonComponents;

function App() {
// const [count, setCount] = useState(0);
// '#3d3da1' : '#5353ea'
useEffect(() => {
// 컴포넌트가 마운트될 때 test.ts의 validateData 함수 실행
validateData();
}, []);

return (
<>
<div>
<a href="https://vitejs.dev" target="_blank">
<img src={viteLogo} className="logo" alt="Vite logo" />
</a>
<a href="https://react.dev" target="_blank">
<img src={reactLogo} className="logo react" alt="React logo" />
</a>
</div>
<h1>Vite + React</h1>
<div className="card">
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
<p>
Edit <code>src/App.tsx</code> and save to test HMR
</p>
</div>
<p className="read-the-docs">
Click on the Vite and React logos to learn more
</p>
</>
<div>
<div style={{marginBottom: '10px'}}>test</div>
<Button EnterColor={'#3d3da1'} LeaveColor={'#5353ea'}/>
</div>
);
}

Expand Down
73 changes: 73 additions & 0 deletions src/shared/components/Button.components.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { useState } from "react";
import Z from "zod";

//interface
//Zod about props
// 1. zod로 props 스키마 정의
const buttonPropsSchema = Z.object({ //4. Error: 런타임 Props 검증, Parse 미사용으로 Error 발생
EnterColor: Z.string(),
LeaveColor: Z.string(),
})

// 2. TypeScript 타입으로 추출
type ButtonProps = Z.infer<typeof buttonPropsSchema>;

// 2-1. 바로 타입만 추출하고 스키마 제거
/**
type ButtonProps = z.infer<
z.object({
EnterColor: z.string(),
LeaveColor: z.string(),
})
>;
*/
// 3. 컴포넌트에 타입 설정: FC Generics로 적용하지 않고 해당 Props에 Type을 적용
// FC 사용방법은 PR Link 참고
const ButtonComponents = (props:ButtonProps) => {
const [isHover, setHover] = useState(false);

// 4-1. 직접적으로 Props 변수를 생성
const { EnterColor, LeaveColor } = props;

// 4-2. 런타임 Props 검증
try {
buttonPropsSchema.parse(props);
console.log("Props validation successful"); // 유효성 검증이 성공하면 이 메시지가 출력됩니다.
} catch (err) {
console.error("Props validation failed", err); // 검증 실패 시 오류 메시지 출력
}

return (
<div>
<div>
<div
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
width: '100px',
height: '50px',
background: isHover ? EnterColor : LeaveColor,
color: 'white',
borderRadius: '7px',
cursor: 'pointer',
}}
onMouseEnter={() => {
setHover(true);
}}
onMouseLeave={() => {
setHover(false);
}}
onClick={() => {
console.log('Button clicked');
}}
role="button" // 접근성 향상
>
Button
</div>
</div>
</div>
)
};

export default ButtonComponents;
67 changes: 67 additions & 0 deletions src/shared/components/Button.components.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { useState } from "react";
import Z from "zod";

//interface
//Zod about props
// 1. zod로 props 스키마 정의
const buttonPropsSchema = Z.object({ //4. Error: 런타임 Props 검증, Parse 미사용으로 Error 발생
EnterColor: Z.string(),
LeaveColor: Z.string(),
})

// 2. TypeScript 타입으로 추출
type ButtonProps = Z.infer<typeof buttonPropsSchema>;

// 2-1. 바로 타입만 추출하고 스키마 제거
/**
type ButtonProps = z.infer<
z.object({
EnterColor: z.string(),
LeaveColor: z.string(),
})
>;
*/
// 3. 컴포넌트에 타입 설정: FC Generics로 적용하지 않고 해당 Props에 Type을 적용
// FC 사용방법은 PR Link 참고
const ButtonComponents = (props:ButtonProps) => {
const [isHover, setHover] = useState(false);

// 4-1. 직접적으로 Props 변수를 생성
const { EnterColor, LeaveColor } = props;
// 4-2. 런타임 Props 검증
buttonPropsSchema.parse(props);

return (
<div>
<div>
<div
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
width: '100px',
height: '50px',
background: isHover ? EnterColor : LeaveColor,
color: 'white',
borderRadius: '7px',
cursor: 'pointer',
}}
onMouseEnter={() => {
setHover(true);
}}
onMouseLeave={() => {
setHover(false);
}}
onClick={() => {
console.log('Button clicked');
}}
role="button" // 접근성 향상
>
Button
</div>
</div>
</div>
)
};

export default ButtonComponents;