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;

 

+ Recent posts