import React from 'react';
import TwoModalButtons from './TwoModalButtons';
import { useModal } from '../store/modal-context';
import useInputs from '../hooks/useInputs';
import calculateTotal from '../util/caculateTotal';
interface OderModalProps {
cart: Cart;
}
const OderModal = ({ cart }: OderModalProps) => {
const { closeModal } = useModal();
const { inputs, handleChange } = useInputs({
fullName: '',
eMail: '',
street: '',
postal: '',
city: '',
});
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
closeModal();
};
const handleClose = () => {
closeModal();
};
return (
<>
<h2>Checkout</h2>
<p>Total Ammount: {calculateTotal(cart)}</p>
<form onSubmit={handleSubmit} className="control">
<div className="control-row">
<label htmlFor="fullName">Full Name</label>
<input
type="text"
id="fullName"
onChange={handleChange}
name="fullName"
value={inputs.fullName}
required
/>
</div>
<div className="control-row">
<label htmlFor="eMail">E-Mail</label>
<input
type="email"
id="eMail"
onChange={handleChange}
value={inputs.eMail}
name="eMail"
required
/>
</div>
<div className="control-row">
<label htmlFor="street">Street</label>
<input
type="text"
id="street"
onChange={handleChange}
value={inputs.street}
name="street"
required
/>
</div>
<div className="postal-city-container">
<div className="control-row">
<label htmlFor="postal">Postal Code</label>
<input
type="text"
id="postal"
onChange={handleChange}
value={inputs.postal}
name="postal"
required
/>
</div>
<div className="control-row">
<label htmlFor="city">City</label>
<input
type="text"
id="city"
onChange={handleChange}
value={inputs.city}
name="city"
required
/>
</div>
</div>
<TwoModalButtons
onClose={handleClose}
submitButtonText="Submit Order"
isFormSubmit={true}
/>
</form>
</>
);
};
export default OderModal;
이런 컴포넌트에
import React from 'react';
import { useModal } from '../store/modal-context';
interface TwoModalButtonsProps {
onSubmit?: () => void;
onClose: () => void;
closeButtonText?: string;
submitButtonText?: string;
isFormSubmit?: boolean;
}
const TwoModalButtons = ({
onSubmit,
onClose,
closeButtonText,
submitButtonText,
isFormSubmit = false,
}: TwoModalButtonsProps) => {
const { closeModal } = useModal();
const handleSubmit = (e: React.MouseEvent<HTMLButtonElement>) => {
if (!isFormSubmit) {
e.preventDefault();
}
if (onSubmit) {
onSubmit();
}
};
const handleClose = (e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
closeModal();
if (onClose) onClose();
};
return (
<div className="modal-actions">
<button type="button" className="text-button" onClick={handleClose}>
{closeButtonText || 'Close'}
</button>
<button
type={isFormSubmit ? 'submit' : 'button'}
className="button"
onClick={handleSubmit}
>
{submitButtonText || 'Submit'}
</button>
</div>
);
};
export default TwoModalButtons;
이런 TowModalButtons를 사용했다
왜 사용했냐하면
모달을 사용하게 되면 버튼이 하나 일때 또는 두개일 때 등등 경우의 수들이 있는데
버튼을 하나하나 만들기 보다는 컴포넌트들을 만들어 관리하면 편할 것 같아서 만들었다
하지만 구현을 할 때 문제가 있었는데
외부 컨테이너에서 form을 사용할 때 input에 required속성이나 input type에 email을 적었는데 validation이 안일어나는 문제였다.
그 이유는
import React from 'react';
import { useModal } from '../store/modal-context';
interface TwoModalButtonsProps {
onSubmit?: () => void;
onClose: () => void;
closeButtonText?: string;
submitButtonText?: string;
}
const TwoModalButtons = ({
onSubmit,
onClose,
closeButtonText,
submitButtonText,
isFormSubmit = false,
}: TwoModalButtonsProps) => {
const { closeModal } = useModal();
const handleSubmit = (e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault(); // 중요
if (onSubmit) {
onSubmit();
}
};
const handleClose = (e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
closeModal();
if (onClose) onClose();
};
return (
<div className="modal-actions">
<button type="button" className="text-button" onClick={handleClose}>
{closeButtonText || 'Close'}
</button>
<button
type='submit'
className="button"
onClick={handleSubmit}
>
{submitButtonText || 'Submit'}
</button>
</div>
);
};
export default TwoModalButtons;
위 코드에서 중요 표시한 부분 때문이었다.
buttons 컴포넌트에 있는 handleSubmit의 e.preventDefault()가 form의 검증 로직을 막았던 것
const handleSubmit = (e: React.MouseEvent<HTMLButtonElement>) => {
if (!isFormSubmit) {
e.preventDefault();
}
if (onSubmit) {
onSubmit();
}
};
수정한 코드 처럼 e.preventDefault를 활성화시키지 않으니깐 원하는데로 작동을 하게 되었다
또한
<button
type={isFormSubmit ? 'submit' : 'button'}
className="button"
onClick={handleSubmit}
>
button의 타입도 중요한데
submit일 때만 form의 validation이 작동하므로 이것도 생각해줘야 한다
물론 이때는 e.preventDefault();를 필요한 부분에 넣어줘야한다
type이 button이면 아무 동작 안하게 된다.
그렇기에 최종적으로 기존의 코드에서
buttons 컴포넌트의 handleSumit안에 있는 e.preventDefault();는 필요하지 않다고 생각되어
제거했다
import React from 'react';
import { useModal } from '../store/modal-context';
interface TwoModalButtonsProps {
onSubmit?: () => void;
onClose: () => void;
closeButtonText?: string;
submitButtonText?: string;
isFormSubmit?: boolean;
}
const TwoModalButtons = ({
onSubmit,
onClose,
closeButtonText,
submitButtonText,
isFormSubmit = false,
}: TwoModalButtonsProps) => {
const { closeModal } = useModal();
const handleSubmit = () => {
if (onSubmit) {
onSubmit();
}
};
const handleClose = (e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
closeModal();
if (onClose) onClose();
};
return (
<div className="modal-actions">
<button type="button" className="text-button" onClick={handleClose}>
{closeButtonText || 'Close'}
</button>
<button
type={isFormSubmit ? 'submit' : 'button'}
className="button"
onClick={handleSubmit}
>
{submitButtonText || 'Submit'}
</button>
</div>
);
};
export default TwoModalButtons;