import { type ComponentPropsWithoutRef } from "react";
type FormProps = ComponentPropsWithoutRef<"form">;
const Form = (props: FormProps) => {
return <form {...props}>{props.children}</form>;
};
export default Form;
이것은 정상작동된다 .
그러나 button을 children으로 넣어주었을 때
button을 클릭시 submit하는 액션이 동작하도록 하고 싶다.
const Form = (props: FormProps) => {
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
const data = new FormData(e.currentTarget);
};
return (
<form onSubmit={handleSubmit} {...props}>
{props.children}
</form>
);
};
e는 FormEvent이며 HTMLFormElement에서 동작하는 이벤트
FromData는 input에 있는 모든 value를 formData로 가져옴
반드시 name값을 지정해 주어야 함
formData -> Object 변환
formData에 접근하려면 form.get메서드를 써야하므로
불편할 수있음
그래서 변환해 줌
const data = Object.fromEntries(formData);
전달받은 onSave메서드에 저장
import { FormEvent, type ComponentPropsWithoutRef } from "react";
type FormProps = ComponentPropsWithoutRef<"form"> & {
onSave: (value: unknown) => void;
};
const Form = (props: FormProps) => {
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
const data = Object.fromEntries(formData);
props.onSave(data);
};
return (
<form onSubmit={handleSubmit} {...props}>
{props.children}
</form>
);
};
export default Form;
실 사용 예시
function App() {
const testRef = useRef(null);
const handleSave = (data: unknown) => {};
return (
<main>
<Form onSave={handleSave}>
접근되나, 에러 발생
위의 에러문구는
내가 알 수없는 곳에서 onSave가 사용되고 있다는것.
예상 못한것.
그러면 객체 구조분해할당을 통해 onSave만 제외한 나머지 otherProps로 넘겨줌
import { FormEvent, type ComponentPropsWithoutRef } from "react";
type FormProps = ComponentPropsWithoutRef<"form"> & {
onSave: (value: unknown) => void;
};
const Form = ({ onSave, children, ...otherProps }: FormProps) => {
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
const data = Object.fromEntries(formData);
onSave(data);
};
return (
<form onSubmit={handleSubmit} {...otherProps}>
{children}
</form>
);
};
export default Form;
리셋 기능 추가
import { FormEvent, type ComponentPropsWithoutRef, useRef } from "react";
type FormProps = ComponentPropsWithoutRef<"form"> & {
onSave: (value: unknown) => void;
};
const Form = ({ onSave, children, ...otherProps }: FormProps) => {
const form = useRef<HTMLFormElement>(null);
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
const data = Object.fromEntries(formData);
onSave(data);
form.current?.reset();
};
return (
<form onSubmit={handleSubmit} {...otherProps} ref={form}>
{children}
</form>
);
};
export default Form;
useImperativeHandle api
form을 호출한 컴포넌트에서
form.current.clear()과 같은 메서드를 호출하고 싶음...?
호출 가능한 함수 노출 하기
forwardedRef를 수신
useImperative는
첫번째 인수 : ref,
두번째 인수 : object를 반환하는 함수
외부 컴포넌트에서
해당 컴포넌트를 호출 할 수 있게 해줌
전체 컴포넌트에 접근하지 않고
useImperativeHandle에서 반환한 object를 참조 할 수 있음
import {
FormEvent,
type ComponentPropsWithoutRef,
useRef,
useImperativeHandle,
forwardRef,
} from "react";
export type FormHandle = {
clear: () => void;
};
type FormProps = ComponentPropsWithoutRef<"form"> & {
onSave: (value: unknown) => void;
};
const Form = forwardRef<FormHandle, FormProps>(
({ onSave, children, ...otherProps }: FormProps, ref) => {
const form = useRef<HTMLFormElement>(null);
useImperativeHandle(ref, () => {
return {
clear() {
console.log("CLEARING");
form.current?.reset();
},
};
});
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
const data = Object.fromEntries(formData);
onSave(data);
form.current?.reset();
};
return (
<form onSubmit={handleSubmit} {...otherProps} ref={form}>
{children}
</form>
);
}
);
export default Form;
'공부기록 > Typescript' 카테고리의 다른 글
#76 (0) | 2023.11.16 |
---|---|
# 65 Context Api 타입지정 (0) | 2023.11.16 |
#57 forwardRef의 타입지정 (0) | 2023.11.15 |
# 54 polymorphic component 만들기 : Container (0) | 2023.11.15 |
# 50 타입의 다양한 활용 유니언 타입, ComponentPropsWithoutRef, Button컴포넌트 (0) | 2023.11.15 |