느려도 한걸음씩

React로 Form다루기 (7) - useIntput 커스텀훅 제작 본문

FE develop/React로 Form 다루기

React로 Form다루기 (7) - useIntput 커스텀훅 제작

hoj0806 2025. 4. 2. 14:05
import { useState } from "react";
import Input from "./Input";
import { isEmail, isNotEmpty, hasMinLength } from "../util/validation.js";

export default function StateLogin() {
  const [enteredValue, setEnteredValue] = useState({
    email: "",
    password: "",
  });

  const [didEdit, setDidEdit] = useState({
    email: false,
    password: false,
  });

  function handleSubmit(e) {
    e.preventDefault();
    console.log(enteredValue);
  }

  function handleInputChange(identifier, e) {
    setEnteredValue((prev) => ({
      ...prev,
      [identifier]: e.target.value,
    }));
    setDidEdit((prevEdit) => ({
      ...prevEdit,
      [identifier]: false,
    }));
  }

  function handleInputBlur(identifier) {
    setDidEdit((prevEdit) => ({
      ...prevEdit,
      [identifier]: true,
    }));
  }

  const emailsIsInvalid =
    didEdit.email &&
    !isEmail(enteredValue.email) &&
    !isNotEmpty(enteredValue.email);

  const passwordIsInValid =
    didEdit.password && hasMinLength(enteredValue.password);

  return (
    <form onSubmit={handleSubmit}>
      <h2>Login</h2>
      <div className='control-row'>
        <Input
          label='Email'
          id='email'
          type='email'
          name='email'
          onBlur={() => handleInputBlur("email")}
          onChange={(e) => handleInputChange("email", e)}
          value={enteredValue.email}
          error={emailsIsInvalid && "Please enter a valid email"}
        />

        <Input
          id='password'
          label='Password'
          type='password'
          name='password'
          onBlur={() => handleInputBlur("password")}
          value={enteredValue.password}
          onChange={(e) => handleInputChange("password", e)}
          error={passwordIsInValid && "Please enter a valid password"}
        />
      </div>

      <p className='form-actions'>
        <button className='button button-flat'>Reset</button>
        <button className='button'>Login</button>
      </p>
    </form>
  );
}

 

state, 함수, 유효성 검사 변수를 커스텀훅으로 관리해보자

 

import { useState } from "react";

export default function useInput(initialValue, validationFn) {
  const [enteredValue, setEnteredValue] = useState(initialValue);
  const [didEdit, setDidEdit] = useState(false);

  const valueValid = validationFn(enteredValue);

  function handleInputChange(e) {
    setEnteredValue(e.target.value);
    setDidEdit(false);
  }

  function handleInputBlur() {
    setDidEdit(true);
  }

  return {
    value: enteredValue,
    hasError: didEdit && !valueValid,
    handleInputChange,
    handleInputBlur,
  };
}

 

import { useState } from "react";
import Input from "./Input";
import { isEmail, isNotEmpty, hasMinLength } from "../util/validation.js";

export default function StateLogin() {
  const [enteredValue, setEnteredValue] = useState({
    email: "",
    password: "",
  });

  const [didEdit, setDidEdit] = useState({
    email: false,
    password: false,
  });

  function handleSubmit(e) {
    e.preventDefault();
    console.log(enteredValue);
  }

  function handleInputChange(identifier, e) {
    setEnteredValue((prev) => ({
      ...prev,
      [identifier]: e.target.value,
    }));
    setDidEdit((prevEdit) => ({
      ...prevEdit,
      [identifier]: false,
    }));
  }

  function handleInputBlur(identifier) {
    setDidEdit((prevEdit) => ({
      ...prevEdit,
      [identifier]: true,
    }));
  }

  const emailsIsInvalid =
    didEdit.email &&
    !isEmail(enteredValue.email) &&
    !isNotEmpty(enteredValue.email);

  const passwordIsInValid =
    didEdit.password && hasMinLength(enteredValue.password);

  return (
    <form onSubmit={handleSubmit}>
      <h2>Login</h2>
      <div className='control-row'>
        <Input
          label='Email'
          id='email'
          type='email'
          name='email'
          onBlur={() => handleInputBlur("email")}
          onChange={(e) => handleInputChange("email", e)}
          value={enteredValue.email}
          error={emailsIsInvalid && "Please enter a valid email"}
        />

        <Input
          id='password'
          label='Password'
          type='password'
          name='password'
          onBlur={() => handleInputBlur("password")}
          value={enteredValue.password}
          onChange={(e) => handleInputChange("password", e)}
          error={passwordIsInValid && "Please enter a valid password"}
        />
      </div>

      <p className='form-actions'>
        <button className='button button-flat'>Reset</button>
        <button className='button'>Login</button>
      </p>
    </form>
  );
}
import Input from "./Input";
import { isEmail, isNotEmpty, hasMinLength } from "../util/validation.js";
import useInput from "../hooks/useInput.js";

export default function StateLogin() {
  const {
    value: emailValue,
    handleInputChange: hnadleEmailChange,
    handleInputBlur: handleEmailBlur,
    hasError: emailHasError,
  } = useInput("", (value) => isEmail(value) && isNotEmpty(value));

  const {
    value: passwordValue,
    handleInputChange: handlePasswordChange,
    handleInputBlur: handlePasswordBlur,
    hasError: passwordHasError,
  } = useInput("", (value) => hasMinLength(value, 6));

  function handleSubmit(e) {
    e.preventDefault();

    if (emailHasError || passwordHasError) {
      return;
    }

    console.log(emailValue, passwordValue);
  }

  return (
    <form onSubmit={handleSubmit}>
      <h2>Login</h2>
      <div className='control-row'>
        <Input
          label='Email'
          id='email'
          type='email'
          name='email'
          onBlur={handleEmailBlur}
          onChange={hnadleEmailChange}
          value={emailValue}
          error={emailHasError && "Please enter a valid email"}
        />

        <Input
          id='password'
          label='Password'
          type='password'
          name='password'
          onBlur={handlePasswordBlur}
          value={passwordValue}
          onChange={handlePasswordChange}
          error={passwordHasError && "Please enter a valid password"}
        />
      </div>

      <p className='form-actions'>
        <button className='button button-flat'>Reset</button>
        <button className='button'>Login</button>
      </p>
    </form>
  );
}

 

 

코드가 매우 간결해졌고 유지보수하기에 쉬워졌다!