React_상품 등록
25 Aug 2023테킷 멋쟁이사자처럼 React
상품 등록
routes.jsx
import ProtectRoute from "./components/ProtectRoute";
import ProductNew from "./pages/Router/ProductNew";
<Route
path="product/new"
element={
<ProtectRoute>
<ProductNew />
</ProtectRoute>
}
/>;
Nav.jsx
{
isAuth && (
<li>
<NavLink
to="/product/new"
className={({ isActive }) =>
isActive ? "font-semibold text-rose-600" : ""
}
>
NEW
</NavLink>
</li>
);
}
ProductNew.jsx
import pb from "@/api/pocketbase";
import { useRef } from "react";
import { Helmet } from "react-helmet-async";
import { toast } from "react-hot-toast";
export default function ProductNew() {
const titleRef = useRef(null);
const colorRef = useRef(null);
const priceRef = useRef(null);
const photoRef = useRef(null);
const uploadPhotoRef = useRef(null);
const handleRegisterProduct = async (e) => {
e.preventDefault();
const formData = new FormData();
formData.append("title", titleRef.current.value);
formData.append("color", colorRef.current.value);
formData.append("price", Number(priceRef.current.value));
formData.append("photo", photoRef.current.files[0]);
try {
await pb.collection("products").create(formData);
toast.success("상품 등록에 성공했습니다.", {
position: "top-center",
ariaProps: {
role: "status",
"aria-live": "polite",
},
});
} catch (error) {
console.log(error);
}
};
const handleDisplayUploadPhoto = (e) => {
const photoFile = e.target.files[0];
const photoUrl = URL.createObjectURL(photoFile);
uploadPhotoRef.current.setAttribute("src", photoUrl);
};
return (
<>
<Helmet>
<title>Register Product - ReactBird</title>
</Helmet>
<div className="flex flex-col gap-6">
<h2 className="text-center text-3xl">상품 등록</h2>
<form encType="multipart/form-data" onSubmit={handleRegisterProduct}>
<div>
<label htmlFor="title">이름</label>
<input
type="text"
ref={titleRef}
name="title"
id="title"
placeholder="상품 이름"
/>
</div>
<div>
<label htmlFor="color">색상</label>
<input
type="text"
ref={colorRef}
name="color"
id="color"
placeholder="색상 이름(예: Black)"
/>
</div>
<div>
<label htmlFor="price">가격</label>
<input
type="text"
ref={priceRef}
name="price"
id="price"
placeholder="가격 (예: 98000원)"
/>
</div>
<div className="relative flex flex-col gap-2 my-4">
<label htmlFor="photo">사진</label>
<input
type="file"
ref={photoRef}
onChange={handleDisplayUploadPhoto}
name="photo"
id="photo"
accept="*.jpg, *.png, *.webp, *.avif"
className="absolute w-full h-full opacity-0"
/>
<div className="h-[140px] bg-slate-200/80 p-2">
<img
className="h-[calc(140px-16px)] border border-slate-400/50 "
ref={uploadPhotoRef}
src="https://placehold.co/84x124?text=PHOTO"
alt=""
/>
</div>
</div>
<div className="flex gap-2">
<button type="submit">등록</button>
<button type="reset">취소</button>
</div>
</form>
</div>
</>
);
}
const photoRef = useRef(null);
const uploadPhotoRef = useRef(null);
<div>
<label htmlFor="photo">사진</label>
<input
type="file"
ref={photoRef}
onChange={handleDisplayUploadPhoto}
name="photo"
id="photo"
accept="*.jpg, *.png, *.webp, *.avif"
/>
<div>
<img ref={uploadPhotoRef} src="" alt="" />
</div>
</div>;
//Display
const handleDisplayUploadPhoto = (e) => {
const photoFile = e.target.files[0];
const photoUrl = URL.createObjectURL(photoFile);
uploadPhotoRef.current.setAttribute("src", photoUrl);
};
//Register
const handleRegisterProduct = async (e) => {
e.preventDefault();
const formData = new FormData();
formData.append("photo", photoRef.current.files[0]);
try {
await pb.collection("products").create(formData);
} catch (error) {
console.log(error);
}
};
<form encType="multipart/form-data" onSubmit={handleRegisterProduct}>
/* ... */
</form>;
- 키워드
- useRef
- 이벤트 핸들러
- handleRegisterProduct
- handleDisplayUploadPhoto
- HTML, JS
인증 확인 페이지
export default function ProtectRoute({ children }) {
const { pathname, search, hash } = useLocation();
const { isAuth } = useAuth();
const wishLocationPath = `${pathname}${search}${hash}`;
useEffect(() => {
if (!isAuth) {
//only development mode
import.meta.env.MODE === "development" && toast.dismiss();
toast("로그인 된 사용자만 이용 가능합니다.");
}
}, [isAuth]);
if (!isAuth) {
return <Navigate to="/signin" state= />;
}
return children;
}
SignIn.jsx
const { state } = useLocation();
const handleSignIn = async (e) => {
e.preventDefault();
//PocketBase SDK 인증 요청
const { email, password } = formState;
try {
await pb.collection("users").authWithPassword(email, password);
if (!state) {
navigate("/");
} else {
navigate(state.wishLocationPath);
}
} catch (error) {
console.error(error);
}
};