아무래도 때가 된 것 같다.
이제 부터는 TypeScript로 리액트를 해보장.
Node와 vscode는 당근으로 이미 설치되어 있어야 한당.
TypeScript가 대략 먼지는? 아래 글을 읽고 오장 (싫다면 그러렴)
2025.01.13 - [자바스크립트] - TypeScript(타입스크립트) 넌 머냥?
거두절미 하고 바로 퐁당 들어가 보장. (실무는 실체적 느끼미가 중요하당)
나의 경우 react-type1(꼭 소문자로)으로 새 폴더를 만들어서 열었당.
Terminal -> New Teriminal을 열고는 아래 명령어를 치장
(Powershell 이 문제를 일으키면 그냥 cmd라고 치고 다시 한당)
npx create-vite@latest .
아래 처럼 선택 하여 본당.

참고로 rolldown-vite는 Experimental(실험적) 이라고 나오는 데, vite에서 적용예정으로
rust 언어로 만들어진 새로운 bundler(여러 흩어진 파일을 하나로 묶어주는)로
그 성능이 기존 bundler 보다 참으로 월등하다고 전해진당
(지금은 선택해도 되공, 안해도 무방하고 무탈하당)

영문자 o를 치고 엔터를 치면 브라우져가 열릴거시당. (이것은 이미 아는 거당)
기본적으로 생성되는 파일들을 보면 아래와 같당. ( 확장자 .ts와 .tsx가 누네띤당)
tsconfig.json 파일도 누네띠는데 열어보면
tsconfig.app.json과 tsconfig.node.json이 그냥 이해된당

필요없는 예시를 위한 파일을 정리를 좀 하장.
assets 폴더와 App.css 파일은 삭제, index.css 파일은 내용은 지우고 껍데기만 남긴당.
main.tsx 는 아래처럼 바꾼당.
import { createRoot } from "react-dom/client";
import "./index.css";
import App from "./App.tsx";
// 아래 라인에 보이는 !는 null 아님을 보증한다는 의미당 희안?
createRoot(document.getElementById("root")!).render(<App />);
App.tsx 는 아래처럼 바꾼당.
function App() {
return (
<>
<h1>너 TypeScript랑 친해?</h1>
</>
);
}
export default App;
브라우져 화면은 아래와 같을꺼당.

이제 어느정도 준비가 된 것 같지만, 기본 alert는 예쁘지 않으닝
기본으로 sweetAlert2도 미리 준비하도록 하장. 터미널에 아래처럼 입력한당.
npm i sweetalert2 sweetalert2-react-content
E7ESwal.tsx 을 src 폴더에 아래내용으로 만들장
import withReactContent from "sweetalert2-react-content";
import Swal from "sweetalert2";
const E7ESwal = withReactContent(Swal);
export default E7ESwal;
준비 끝 (준비 작업도 참 길당)
오늘은 은근 꽤나 많이 자주 질문 받는 form안에 submit 버튼이 여러개 있을 때
어느 submit버튼을 눌렀는지를 알아내는 걸 해보장.
(typescript를 쓰면 추가적인 질문이 발생하게 된당.)
FormSample.tsx 를 src 폴더에 아래처럼 맹글장
import type { FormEvent } from "react";
import E7ESwal from "./E7ESwal";
function FormSample() {
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
const nativeEvent = e.nativeEvent as SubmitEvent; // 형변환을 해야 submitter가 나옴!
console.log(nativeEvent.submitter); // 어느 버튼이 submit을 발생시켰는지 안당.
const clickedButton = nativeEvent.submitter;
console.log(clickedButton?.innerHTML); // ? 알디용
if (clickedButton?.innerHTML === "눌러방") { // innerText를 써도 된당.
E7ESwal.fire("눌러방 눌렀네엥");
} else {
E7ESwal.fire("누를깡 눌렀구망");
}
};
return (
<div>
<form onSubmit={handleSubmit}>
<button>눌러방</button>
<br />
<button>누를깡</button>
<br />
</form>
</div>
);
}
export default FormSample;
뽀인트는 form이벤트의 submitter에 어느 버튼이 submit을 발생시켰는지가 담겼는데..
Typescript에선 아래처럼 형변환을 해줘야 submitter를 읽을 수 있당.
const nativeEvent = e.nativeEvent as SubmitEvent
e는 진짜 이벤트를 품고 있는 가짜 이벤트고(멋진 말로 syntheticeven라 한당)
e.nativeEvent가 진짜 이벤트당!
App.tsx 를 아래처럼 수정하장
import FormSample from "./FormSample";
function App() {
return (
<>
<h1>너 TypeScript랑 친해?</h1>
<FormSample />
</>
);
}
export default App;
화면에서 테스트 해보면 잘 됨을 알수 있당.
사실 React에선 거의 사용되진 않지만(왜?) 일반 html이나 jsp라면 submit 버튼의
form관련 속성을 이용해서 쉽게 버튼 구분 필요없이 원하는 action을 취할 수 있당.
이건 그냥 메인 흐름과 상관없이 참고롱 해보장.
formtest.html을 public 폴더에 아래처럼 맹글고
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<form>
<input type="text" name="myname" value="E7E"><br/>
<button formaction="km.html">경미닝</button><br/>
<button formaction="mk.html">밍겨닝</button><br/>
<button formaction="yw.html">예워닝</button><br/>
<button formaction="ksj.html">금수저닝</button>
</form>
</body>
</html>
주소 표시줄에 http://localhost:5173/formtest.html 를 입력해서 결과를 확인해 보장
(port 번호는 본인에 맞게, 나의 경우 5173 이당.)
주소 표시줄의 변화를 누니 인식했다면 그걸로 족하당.
useRef Hook을 이용해서도 submit 버튼을 구분하는 걸 한번 해보장.
FormSample.tsx 를 아래 처럼 고쳐보장.
import { useRef, type FormEvent } from "react";
import E7ESwal from "./E7ESwal";
function FormSample() {
const myForm = useRef(null);
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
const nativeEvent = e.nativeEvent as SubmitEvent; // 형변환을 해야 submitter가 나옴!
console.log(nativeEvent.submitter);
const clickedButton = nativeEvent.submitter!;
const eForm = myForm.current!;
if (clickedButton !== eForm["ksj"]) {
E7ESwal.fire("눌러방 눌렀네엥");
} else {
E7ESwal.fire("누를깡 눌렀구망");
}
};
return (
<div>
<form ref={myForm} onSubmit={handleSubmit}>
<button name="smk">눌러방</button>
<br />
<button name="ksj">누를깡</button>
<br />
</form>
</div>
);
}
export default FormSample;
결과는 역시 예측대로당.

당신은 열정이 넘치기에 여기서 끝낸다면 화가 산만큼 커져 화산이 될게 뻔하당.
form하면 거져 생각나는 라이브러리 react-hook-form을 한번 사용해보도록 하장
https://www.npmjs.com/package/react-hook-form
먼저 지레 설치지 않도록 설칭, Terminal에 아래처럼 입력
npm i react-hook-form
HookFormSample.tsx 를 src 폴더에 맹글장.
import { useForm } from "react-hook-form";
function HookFormSample() {
const {
register,
handleSubmit,
formState: { errors },
} = useForm();
return (
<div style={{ border: "5px groove blue", marginBottom: 10 }}>
<form onSubmit={handleSubmit((data) => console.log(data))}>
이름:
<input
autoComplete={"off"}
{...register("name", { required: true, minLength: 2 })}
/>
<br />
나이:
<input
{...register("age", {
required: true,
pattern: /\d{2}/,
min: 20,
max: 99,
})}
/>
<br />
별명:
<input {...register("alias")} />
<br />
{errors.name && <p style={{ color: "red" }}> 이름 제대로 써달라공</p>}
{errors.age && <p style={{ color: "red" }}> 이거 나이 맞엉?</p>}
<button style={{ color: "magenta" }}>체킁</button>
</form>
</div>
);
}
export default HookFormSample;
뽀인또는 useForm 훅인디, 개인적인 생각에도 아주 잘 만들었당.
개발자들의 form 사용 패턴을 잘 분석했다는 느끼미가 다가서는데,
Java Spring을 해본 사람이라면 Spring 서버 태그인 <form:form> 태그와
비슷하다는 뉘앙스를 떨칠 수 없음이당.~~
useForm 훅 함수가 return 해주는 register, handleSubmit, formState 3개만
사용하면 쉽게 form에 유효성 검사와 최종 form이 가진 값들을 덩어리로
사용할 수 있당. formState에서는 erros 객체만 구조분해롱 꺼냈당.
이해가 되면 복사 / 붙여넣기 사용이 당근 나라 기본 사용법이 된당.
App.tsx 를 아래처럼 수정하장.
import FormSample from "./FormSample";
import HookFormSample from "./HookFormSample";
function App() {
return (
<>
<h1>너 TypeScript랑 친해?</h1>
<HookFormSample />
<FormSample />
</>
);
}
export default App;
당근 나라에서 확인한 결과는 아래와 같당.

직관적 느끼미가 빠르고 강한 사람은 느꼈을 거시당.
TypeScript를 쓴다고 해서 엄청나게 많은 코드 변화를 감당해야 하는 게 아니라는 것!
그저 lint(훈수꾼)이 밑줄 그어주는 부분에만 조금씩 대응해 주면 된다는 것!
그저 사용하다 보면 자연스럽게 TypeScript 스타일도 품을 수 있게 될꺼이당.
천천히 그저 가면 된당.
인간이라면..., 사람이라면...
수없는 반복이 지겨울 수 밖에.. 재미없을 수 밖에..
자존감이 상할 수 밖에..
반복에 댓가를 살짝 얹으면 상황은 역전된당.
도박이란 조미료를 흔들어 뿌리면 된당.
도박이 해석하는 인간은, 사람은
승리, 약탈, 소유, 우위,지배를 재밌다고 한다.
반복되는 로직!, 반복에 반복인 코딩과 도박하자.
스스로에게 베팅하라.
분명 긴 꼬리 반복 뒤에 승리의 옴팡진 댓가가 있음을..
아마도 그건 반복을 없앤 새로운 테크닉일까
성의없이 의무로 반복된 kiss는
식지않는 kiss, sunkiss를 기다린당.
https://www.youtube.com/watch?v=5PS2cJsSJrI
| React(리액트) 티키타카 18 ( rc-tree 트리 컴포넌트) (2) | 2025.11.04 |
|---|---|
| React(리액트) 티키타카 33 SVAR Gantt(업그레이드) (3) | 2025.11.03 |
| 템플릿 (6) | 2025.06.27 |
| React(리액트) 티키타카 37 (Route 이해) (4) | 2025.05.16 |
| React(리액트) 티키타카 36 (Context API) (2) | 2025.05.13 |