React 컴포넌트 이벤트 + Tailwind 사용

조영래·2024년 7월 23일
0
post-thumbnail
post-custom-banner

React 컴포넌트 이벤트

컴포넌트 (Component)란?

리액트는 화면에서 UI 요소를 구분할 때 '컴포넌트'라는 단위를 사용한다. 쉽게 말하면 리액트에서 앱을 이루는 가장 작은 조각이라고 할 수 있고, 레고 블록으로 집을 쌓게 된 경우 하나의 블록이 '컴포넌트'라고 할 수 있다.
반복적인 html 축약할때, 큰 페이지들, 자주변경되는 것들 때 사용하면 좋다

// ProfileCard.tsx
type TProfileCardProps = {
  backgroundImage: string;
  userImage: string;
  userName: string;
  instarId: string;
  onFollowClick: () => void;
};
const ProfileCard = ({
  backgroundImage,
  userImage,
  userName,
  instarId,
  onFollowClick,
}: TProfileCardProps) => {
  return (
    <>
      <article className="card">
          <img className="prof-img" src={userImage} alt="profile-pic" />
          <h3 className="alias">{instarId}</h3>
          <p className="username">{userName}</p>
          <button onClick={onFollowClick}>Follow</button>
        </div>
      </article>
    </>
  );
};
export default ProfileCard;
// App.tsx
// login 상태일때, 아닐때 표현
import ProfileCard from "./ProfileCard";
const App = () => {
  const isLoggedin = true;
  return (
    <>
      {isLoggedin && (
        <ProfileCard
          userImage="https://images.pexels.com/photos/415829/pexels"
          userName="@sallytheramos"
          instarId="Sally Ramos"
          onFollowClick={() => alert("Followed")}
        />
      )}
    </>
  );
};
export default App;

onChange, onClick

onChange

<input> <textarea> <select> 와 같은 폼(Form) 엘리먼트는 사용자의 입력값을 제어하는 데 사용한다
React 에서는 이러한 변경될 수 있는 입력값을 일반적으로 컴포넌트의 state 로 관리하고 업데이트한다.
onChange 이벤트가 발생하면 e.target.value 를 통해 이벤트 객체에 담겨있는 input 값을 읽어올 수 있다.
// ex)
function NameForm() {
  const [name, setName] = useState("");
  const handleChange = (e) => {
    setName(e.target.value);
  }
  return (
    <div>
      <input type="text" value={name} onChange={handleChange}></input>
      <h1>{name}</h1>
    </div>
  )
};

onClick

onClick 이벤트는 말 그대로 사용자가 클릭이라는 행동을 하였을 때 발생하는 이벤트이다. 
버튼이나 <a> tag 를 통한 링크 이동 등과 같이 주로 사용자의 행동에 따라 애플리케이션이 반응해야 할 때 자주 사용한다.
function NameForm() {
  const [name, setName] = useState("");
  const handleChange = (e) => {
    setName(e.target.value);
  };
  const handleClick = () => {
  alert(name);
  };
  return (							
    <div>
      <input type="text" value={name} onChange={handleChange}></input>
      <button onClick={handleClick}>Button</button> 
      <h1>{name}</h1>
    </div>
  );
};

Children Prop

React 컴포넌트에서 children은 부모 컴포넌트 사이에서 자식 컴포넌트를 가리키는 특별한 prop을 말한다. 여기서 중요한 점은, children prop은 명시적으로 전달하지 않아도 부모 컴포넌트 사이의 내용을 자동으로 전달받는다는 것이다. 이를 통해 컴포넌트가 재사용 가능한 '틀' 역할을 하도록 할 수 있다.

// children prop
// RedColor.tsx
const RedColor = ({ children }: { children: React.ReactNode }) => {
  return (
    <>
      <div style={{ color: "red", fontSize: "50px" }}>{children}</div>
    </>
  );
};
export default RedColor;
// App.tsx
import RedColor from "./RedColor";
const App = () => {
  return (
    <>
      <RedColor>
        I <span style={{ textDecoration: "underline" }}>want</span> to Text
      </RedColor>
    </>
  );
};
export default App;

이런 방식으로 children prop을 사용하면, 컴포넌트를 재사용 가능한 '틀'처럼 사용할 수 있으며, 이 틀 안에 어떤 내용을 넣을지는 컴포넌트를 사용하는 측에서 결정할 수 있게 된다. 이는 코드의 재사용성을 높이고 유연성을 제공한다.

Props

Props는 부모 컴포넌트가 자식 컴포넌트에게 전달하는 값이다.
Props는 객체여서 넘겨 받을때, 자식 컴포넌트에서 'props.이름'으로 접근할수 있다, 비구조화 할당도 가능하다

// Greeting.tsx
const Greeting = (props: { name: string; age: number }) => {
  return (
    <>
      <h1>
        Hello, {props.name} {props.age}
      </h1>
    </>
  );
};
export default Greeting;
// Eat.tsx
const Eat = (props: { name: string; age: number; onFinishEat: () => void }) => {
  return (
    <>
      <h1>
        {props.name} - {props.age} 님이 식사를 시작합니다
      </h1>
      <button onClick={props.onFinishEat}>식사완료</button>
    </>
  );
};
export default Eat;

Interface, Type 타입으로 지정해 받을 수 있다.

// interface는 type폴더에 따로 지정해 전역에서 사용할수있다. 앞에 I를 붙여주면 더 알아보기 쉽다
// index.d.ts
export interface IGreetingProps = {
  name: string;
  age: number;
};
// type은 적은 곳에서만 사용이 가능하며, 앞에 T를 붙여주면 더 알아보기 쉽다
type TGreetingProps = {
  name: string;
  age: number;
};
// 받을때 interface는 import 해줘야한다. type폴더라는 곳에 따로 지정을 해줬으니
const Greeting = (props: IGreetingProps) => {}
const Greeting = (props: TGreetingProps) => {}

Rest

button, input 같은 태그에 {...rest}로 props를 받아오면, rest 안에 있는 객체안에 있는 값들을 모두 button, input 등 태그에 설정을 해준다.

// Input.tsx
type TInputProps = React.ComponentPropsWithoutRef<"input">;
// html 태그이름이랑 속성명이 이름 똑같을때 똑같아야함
// React.ComponentPropsWithoutRef 사용시
const Input = ({ ...rest }: TInputProps) => {
  return (
    <>
      <input
        className="w-[240px] h-[44px] rounded-lg placeholder::text-[#acacac] border
        border-[#4F4F4F] py-[13.5px] px-[16px] outline-none text-sm outline-none"
        {...rest}
      />
    </>
  );
};
export default Input;
// App.tsx
import Input from "./Input";
const App = () => {
  return (
    <>
      <div className="flex justify-center items-center min-h-screen">
        <Input type="text" placeholder="Enter Todo List" />
      </div>
    </>
  );
};
export default App;

Tailwind twmerge

import { twMerge } from "tailwind-merge";
import { twJoin } from "tailwind-merge";
// twMerge 뒤에께 앞에걸 덮어씌움
// twJoin 앞에께 뒤에꺼를 덮음
const App = () => {
  // loggedIn = true -> text-5xl text-rose-500
  // loggedIn = false -> text-3xl
  const isLoggedIn = true;
  return (
    <>
      {/* <h1 className={isLoggedIn ? "text-5xl" : "text-3xl"}>aaa</h1> */}
      // twMerge로 변경
      <h1 className={twMerge("text-3xl", isLoggedIn ? "text-5xl" : "")}>aaa</h1>
    </>
  );
};
export default App;
profile
난될놈이야
post-custom-banner

0개의 댓글