다음과 같이 Input.tsx 컴포넌트를 만들면 됩니다. TypeScript로 props를 정의하여 재사용할 수 있도록 했어요.
그리고 외부 페이지에서 어떻게 사용할 수 있는지도 함께 예제를 보여줄게요.
Input.tsx (컴포넌트)import React from "react";
interface InputProps {
type: string;
placeholder?: string;
value: string;
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
className?: string;
}
const Input: React.FC<InputProps> = ({ type, placeholder, value, onChange, className }) => {
return (
<input
type={type}
placeholder={placeholder}
value={value}
onChange={onChange}
className={`text-[#A3A7AF] bg-[#F1F3F6] w-full p-2 border rounded mb-2 px-5 focus:outline-none ${className}`}
/>
);
};
export default Input;
App.tsx (사용 예시)import React, { useState } from "react";
import Input from "./components/Input"; // 경로에 맞게 import
const App: React.FC = () => {
const [userId, setUserId] = useState("");
return (
<div className="p-5">
<Input
type="text"
placeholder="아이디"
value={userId}
onChange={(e) => setUserId(e.target.value)}
className="border-none"
/>
<p className="mt-2">입력한 아이디: {userId}</p>
</div>
);
};
export default App;
Input.tsx에서 props를 받아서 재사용 가능한 컴포넌트를 만들었어요.className을 props로 받아서 필요한 경우 추가 스타일을 적용할 수 있도록 했어요.App.tsx에서 useState로 상태를 관리하며, Input 컴포넌트를 사용해서 userId 값을 업데이트하도록 구현했어요.
margin: auto를 사용하여 요소를 가운데 정렬하려면 몇 가지 조건이 필요합니다.
margin: auto는 블록 요소의 좌우 마진을 자동으로 설정하여 가운데 정렬합니다.
.container {
width: 300px; /* 너비 지정 필수 */
margin: auto;
}
✅ 필수 조건: width를 지정해야 함.
display: flex를 사용하면 가로뿐만 아니라 세로 정렬도 가능함.
.parent {
display: flex;
justify-content: center; /* 가로 중앙 정렬 */
align-items: center; /* 세로 중앙 정렬 */
height: 100vh; /* 부모 요소 높이 지정 */
}
text-align: center)margin: auto는 블록 요소에서만 동작하므로, 인라인 요소는 text-align: center; 사용.
.parent {
text-align: center;
}
.child {
display: inline-block; /* 블록 성질 추가 */
}
useEffect 추가로 문제 해결된 이유이 문제의 핵심은 React의 상태 업데이트가 즉시 반영되지 않기 때문입니다.
React의 상태 업데이트(setState)는 비동기적으로 처리되므로, setPwInputOpen(false);가 호출된 직후에 pwInputOpen 값이 즉시 false로 변경되지 않습니다.
const handleCancel = () => {
console.log("취소 버튼 클릭됨");
setPwInputOpen(false);
};
setPwInputOpen(false); 호출 → React가 리렌더링을 예약함pwInputOpen 값이 변경되기 전의 상태를 사용함 setPwInputOpen(false); 호출 직후에도 pwInputOpen 값은 아직 true임ChangePwBox가 사라지지 않음useEffect가 해결한 방식useEffect(() => {
console.log("pwInputOpen 상태 변경됨:", pwInputOpen);
}, [pwInputOpen]);
useEffect는 pwInputOpen 값이 변경될 때마다 실행됨setPwInputOpen(false);가 호출된 후, React가 리렌더링을 진행하면서 이제야 pwInputOpen 값이 실제로 false로 반영됨useEffect가 실행되면서 "pwInputOpen 상태 변경됨: false" 로그가 출력됨 → 리렌더링 확인 가능ChangePwBox가 사라지고 "변경" 버튼이 다시 나타남setPwInputOpen(false); 실행 → 상태 업데이트 예약 (즉시 반영 아님)pwInputOpen 값을 false로 반영useEffect 실행 (pwInputOpen 값이 변경되었기 때문)ChangePwBox가 사라지고 "변경" 버튼이 보임useEffect 없이 해결하는 방법useEffect 없이도 올바르게 동작하게 하려면 리렌더링을 확실히 유도하는 방식으로 상태 업데이트를 관리해야 합니다.
const handleCancel = () => {
setPwInputOpen(false);
};
setTimeout으로 강제 리렌더링 확인const handleCancel = () => {
setPwInputOpen(false);
setTimeout(() => {
console.log("상태 변경 후 pwInputOpen 값:", pwInputOpen);
}, 0);
};
setTimeout을 사용하면 React가 현재 이벤트 루프가 끝난 후 상태 업데이트를 반영하도록 유도할 수 있음useEffect가 해결책이 되었는가?useEffect는 리렌더링 이후 상태가 변경되었을 때 실행되는 코드이므로, pwInputOpen 상태 변경이 반영된 이후 로직이 실행되었음✅ useEffect를 추가하는 것이 아니라, React 상태 관리 특성을 이해하고 로직을 설계하는 것이 중요
✅ React의 상태 변경이 비동기적으로 처리된다는 점을 기억하고, 조건부 렌더링을 제대로 구성하면 useEffect 없이도 해결 가능