상세 컨텐츠

본문 제목

React With TypeScript 체킁1

React

by e7e 2025. 10. 21. 20:03

본문

아무래도 때가 된 것 같다.

이제 부터는 TypeScript로 리액트를 해보장.

Nodevscode는 당근으로 이미 설치되어 있어야 한당.

 

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

 

관련글 더보기