[TIL] 0626 | React with Redux, Next.js, TypeScript

TeasanΒ·2022λ…„ 6μ›” 26일
0

TIL

λͺ©λ‘ 보기
17/36
post-thumbnail

λͺ©μ°¨

  • μ‚¬μš©μž μ •μ˜ ν›… μž¬μ‚¬μš©ν•˜κΈ°
  • μ‚¬μš©μž μ •μ˜ ν›… μ—°μŠ΅ν•˜κΈ°

✧ μ‚¬μš©μž μ •μ˜ ν›… μž¬μ‚¬μš©ν•˜κΈ°

  • name에 Input에 λŒ€ν•΄μ„œ use-input μ»€μŠ€ν…€ 훅을 μ΄μš©ν•œ κ²ƒμ²˜λŸΌ, λ™μΌν•˜κ²Œ λ³΅μ‚¬ν•΄μ„œ ν•΄λ‹Ή useInput μ»€μŠ€ν…€ 훅을 κ°€μ Έμ˜€κ³ , name에 μ μš©ν•œ κ²ƒμ²˜λŸΌ μ»€μŠ€ν…€ ν›…μ—μ„œ λ°˜ν™˜ν•œ κ°’λ“€μ˜ 이름을 email μ „μš©μœΌλ‘œ μˆ˜μ •ν•΄μ€€λ‹€.
// name
const {
  value: enteredName,
  isValid: enteredNameIsValid,
  hasError: nameInputHasError,
  valueChangeHandler: nameChangeHandler,
  inputBlurHandler: nameBlurHandler,
  reset: resetNameInput,
} = useInput((value) => value.trim() !== "");

// e-mail
const {
  value: enteredEmail,
  isValid: enteredEmailIsValid,
  hasError: emailInputHasError,
  valueChangeHandler: eamilChangeHandler,
  inputBlurHandler: eamilBlurHandler,
  reset: resetEmailInput,
} = useInput((value) => value.trim() !== "" && value.includes("@"));
  • 그리고 더이상 μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” useState둜 μž‘μ„±ν–ˆλ˜ κ°’κ³Ό ν•΄λ‹Ή μ»΄ν¬λ„ŒνŠΈ λ‚΄μ—μ„œλ§Œ μ‚¬μš©ν–ˆλ˜ μ „μš© ν•¨μˆ˜λ“€μ„ λͺ¨λ‘ μ§€μ›Œμ€€λ‹€.
// const [enteredEmail, setEnteredEmail] = useState("");
// const [enteredEmailTouched, setEnteredEmailTouched] = useState(false);

// const enteredEmailIsValid =
//   enteredEmail.trim() !== "" && enteredEmail.includes("@");
// const emailInputIsInvalid = !enteredEmailIsValid && enteredEmailTouched;
  • 폼을 μ œμΆœν•  λ•Œμ— μœ νš¨μ„±μ„ κ²€μ¦ν•˜κ³ , input 창을 λ¦¬μ…‹ν•΄μ£ΌλŠ” formSubmitssionHandler ν•¨μˆ˜μ—λ„ useStateλ₯Ό μ‚¬μš©ν•΄μ„œ λ¦¬μ…‹ν•΄μ£Όμ—ˆλ˜ 뢀뢄을 μ§€μš°κ³ , μ»€μŠ€ν…€ ν›…μ˜ 리셋 ν•¨μˆ˜μΈ resetEmailInput(reset)을 ν˜ΈμΆœν•΄ μ€€λ‹€.
const formSubmitssionHandler = (event) => {
  event.preventDefault();

  if (!enteredNameIsValid || !enteredEmailIsValid) {
    return;
  }

  resetNameInput();

  // setEnteredEmail("");
  // setEnteredEmailTouched(false);
  resetEmailInput();
};
  • useInput μ»€μŠ€ν…€ ν›…μ—μ„œ μ‚¬μš©ν•˜λŠ” hasError λ³€μˆ˜λ₯Ό 기반으둜 μ‚Όν•­μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•œ class μ„€μ • λ˜ν•œ μ»€μŠ€ν…€ ν›…μ—μ„œ κ°€μ Έμ˜¨ emailInputHasError으둜 μˆ˜μ •ν•΄μ€€λ‹€.
const emailInputClasses = emailInputHasError // true 이면,
  ? "form-control invalid" // κ²½κ³  css
  : "form-control";
  • email을 μž…λ ₯ν•˜λŠ” input νƒœκ·Έμ— 포인터 ν•΄μ£Όμ—ˆλ˜ ν•¨μˆ˜λ„ useInput μ»€μŠ€ν…€ ν›…μ˜ ν•¨μˆ˜λ“€λ‘œ λŒ€μ²΄ν•΄μ€€λ‹€. μ•„λž˜μ˜ μ‚Όν•­μ—°μ‚°μžλ₯Ό μ΄μš©ν•œ 뢀뢄도 emailInputHasError둜 μˆ˜μ •ν•΄μ€€λ‹€.
<input
  type="email"
  id="email"
  onChange={eamilChangeHandler}
  onBlur={eamilBlurHandler}
  value={enteredEmail}
/>;
{
  emailInputHasError && <p className="error-text">Email must not be empty.</p>;
}

정리

  • μ €μž₯ν•˜κ³  확인해보면 이전과 λ™μΌν•˜κ²Œ μž‘λ™λ˜κ³  μžˆμŒμ„ μ•Œ 수 μžˆλ‹€. λ‘˜λ‹€ 이전과 λ™μΌν•˜κ²Œ μž‘λ™ν•˜κ³  μžˆμ§€λ§Œ ν˜„μž¬μ˜ μ½”λ“œμ™€ λΉ„κ΅ν•˜μ—¬ μ•Œμˆ˜ μžˆλŠ” 것은 ν˜„μž¬μ˜ μ½”λ“œκ°€ 훨씬 κ°„κ²°ν•˜κ³  μ€‘λ³΅λœ μ½”λ“œκ°€ μ μ–΄μ‘Œλ‹€λŠ” 사싀이닀.

✧ μ‚¬μš©μž μ •μ˜ ν›… μ—°μŠ΅ν•˜κΈ°

  • μ§€κΈˆκΉŒμ§€ 배운 λ‚΄μš©μ„ λ°”νƒ•μœΌλ‘œ SimpleInput μ»΄ν¬λ„ŒνŠΈ λŒ€μ‹ , BasicForm μ»΄ν¬λ„ŒνŠΈλ₯Ό μ΄μš©ν•΄μ„œ μ΄μ „μ²˜λŸΌ μ»€μŠ€ν…€ 훅을 μ΄μš©ν•œ μœ νš¨μ„± 검증에 도전해볼 것이닀.
// import SimpleInput from "./components/SimpleInput";
import BasicForm from "./components/BasicForm";

function App() {
  return (
    <div className="app">
      {/* <SimpleInput /> */}
      <BasicForm />
    </div>
  );
}

export default App;
  • κ°€μž₯ λ¨Όμ €, App μ»΄ν¬λ„ŒνŠΈ 내뢀에 SimpleInput μ»΄ν¬λ„ŒνŠΈ λŒ€μ‹  BasicForm μ»΄ν¬λ„ŒνŠΈλ‘œ λŒ€μ²΄ν•œλ‹€.

BasicForm.js

before

const BasicForm = (props) => {
  return (
    <form>
      <div className="control-group">
        <div className="form-control">
          <label htmlFor="name">First Name</label>
          <input type="text" id="name" />
        </div>
        <div className="form-control">
          <label htmlFor="name">Last Name</label>
          <input type="text" id="name" />
        </div>
      </div>
      <div className="form-control">
        <label htmlFor="name">E-Mail Address</label>
        <input type="text" id="name" />
      </div>
      <div className="form-actions">
        <button>Submit</button>
      </div>
    </form>
  );
};

export default BasicForm;

after

import useInput from "../hooks/use-input";

const BasicForm = (props) => {
  // First Name
  const {
    value: enteredFirstName,
    isValid: enteredFirstNameIsValid,
    hasError: firstNameInputHasError,
    valueChangeHandler: firstNameChangeHandler,
    inputBlurHandler: firstNameInputBlurHandler,
    reset: resetFirstName,
  } = useInput((value) => value.trim() !== "");

  // Last Name
  const {
    value: enteredLastName,
    isValid: enteredLastNameIsValid,
    hasError: lastNameInputHasError,
    valueChangeHandler: lastNameChangeHandler,
    inputBlurHandler: lastNameInputBlurHandler,
    reset: resetLastName,
  } = useInput((value) => value.trim() !== "");

  // email
  const {
    value: enteredEmail,
    isValid: enteredEmailIsValid,
    hasError: emailInputHasError,
    valueChangeHandler: emailChangeHandler,
    inputBlurHandler: emailInputBlurHandler,
    reset: resetEmail,
  } = useInput((value) => value.trim() !== "" && value.includes("@"));

  let formIsValid = false;

  if (
    enteredFirstNameIsValid &&
    enteredLastNameIsValid &&
    enteredEmailIsValid
  ) {
    formIsValid = true;
  } else {
    formIsValid = false;
  }

  const formSubmitssionHandler = (e) => {
    e.preventDefault();

    if (
      !enteredFirstNameIsValid ||
      !enteredLastNameIsValid ||
      !enteredEmailIsValid
    ) {
      return;
    }

    resetFirstName();
    resetLastName();
    resetEmail();
  };

  const firstNameInputClasses = firstNameInputHasError
    ? "form-control invalid"
    : "form-control";

  const lastNameInputClasses = lastNameInputHasError
    ? "form-control invalid"
    : "form-control";

  const emailInputClasses = emailInputHasError
    ? "form-control invalid"
    : "form-control";

  return (
    <form onSubmit={formSubmitssionHandler}>
      <div className="control-group">
        <div className={firstNameInputClasses}>
          <label htmlFor="name">First Name</label>
          <input
            type="text"
            id="name"
            value={enteredFirstName}
            onChange={firstNameChangeHandler}
            onBlur={firstNameInputBlurHandler}
          />
          {firstNameInputHasError ? (
            <p className="error-text">First Name 이 λΉ„μ–΄μžˆμŠ΅λ‹ˆλ‹€.</p>
          ) : (
            ""
          )}
        </div>
        <div className={lastNameInputClasses}>
          <label htmlFor="name">Last Name</label>
          <input
            type="text"
            id="name"
            value={enteredLastName}
            onChange={lastNameChangeHandler}
            onBlur={lastNameInputBlurHandler}
          />

          {lastNameInputHasError ? (
            <p className="error-text">Last Name 이 λΉ„μ–΄μžˆμŠ΅λ‹ˆλ‹€.</p>
          ) : (
            ""
          )}
        </div>
      </div>
      <div className={emailInputClasses}>
        <label htmlFor="name">E-Mail Address</label>
        <input
          type="text"
          id="email"
          value={enteredEmail}
          onChange={emailChangeHandler}
          onBlur={emailInputBlurHandler}
        />
        {emailInputHasError ? (
          <p className="error-text">E-Mail μ£Όμ†Œκ°€ λ‹€λ¦…λ‹ˆλ‹€.</p>
        ) : (
          ""
        )}
      </div>
      <div className="form-actions">
        <button disabled={!formIsValid}>Submit</button>
      </div>
    </form>
  );
};

export default BasicForm;

우리의 훅와 지식을 μƒˆλ‘œμš΄ ν˜•νƒœμ— μ μš©ν•˜κΈ°

μΆ”κ°€μ μœΌλ‘œ μˆ˜μ •ν•œ λΆ€λΆ„

  • useInput에 μ „λ‹¬ν•˜λŠ” ν•¨μˆ˜ 둜직 λ”°λ‘œ μ „μ—­ λ³€μˆ˜λ‘œ λΉΌκΈ°.
const isNotEmpty = (value) => value.trim() !== "";
const isEmail = (value) => value.includes("@") && isNotEmpty;

// Name
const {
  value: enteredLastName,
  isValid: enteredLastNameIsValid,
  hasError: lastNameInputHasError,
  valueChangeHandler: lastNameChangeHandler,
  inputBlurHandler: lastNameInputBlurHandler,
  reset: resetLastName,
} = useInput(isNotEmpty);

// email
const {
  value: enteredEmail,
  isValid: enteredEmailIsValid,
  hasError: emailInputHasError,
  valueChangeHandler: emailChangeHandler,
  inputBlurHandler: emailInputBlurHandler,
  reset: resetEmail,
} = useInput(isEmail);
  • μ‚Όν•­ μ—°μ‚°μžκ°€ μ•„λ‹ˆλΌ &&둜 둜직 κ°„κ²°ν•˜κ²Œ 쀄이기
// {
//   firstNameInputHasError ? (
//     <p className="error-text">First Name 이 λΉ„μ–΄μžˆμŠ΅λ‹ˆλ‹€.</p>
//   ) : (
//     ""
//   );
// }

{
  firstNameInputHasError && (
    <p className="error-text">First Name 이 λΉ„μ–΄μžˆμŠ΅λ‹ˆλ‹€.</p>
  );
}
  • 각각의 μœ νš¨μ„± κ°’μœΌλ‘œ κ²€μ‚¬ν•˜κΈ° λ³΄λ‹€λŠ” λ³€μˆ˜ formIsValid κ°’ ν•˜λ‚˜λ‘œ 검사할 수 μžˆλ‹€. formIsValidλ₯Ό μ΄μš©ν•΄μ„œ λ²„νŠΌμ„ λΉ„ν™œμ„±ν™” ν–ˆκΈ° λ•Œλ¬Έμ— λ²„νŠΌμ„ λΉ„ν™œμ„±ν™”ν•œ μƒνƒœμ—μ„œλŠ” μ• μ΄ˆμ— 폼을 μ œμΆœν•  수 μ—†κΈ° λ•Œλ¬Έμ΄λ‹€.
let formIsValid = false;

if (
  enteredFirstNameIsValid &&
  enteredLastNameIsValid &&
  enteredEmailIsValid
) {
  formIsValid = true;
} else {
  formIsValid = false;
}
...

const formSubmitssionHandler = (e) => {
  e.preventDefault();

  if (
    // !enteredFirstNameIsValid ||
    // !enteredLastNameIsValid ||
    // !enteredEmailIsValid
    !formIsValid
  ) {
    return;
  }

  // first name reset
  resetFirstName();
  // last name reset
  resetLastName();
  // email reset
  resetEmail();
};
  • μ €μž₯ν•˜κ³  확인해보면, SimpleInputκ³Ό λ™μΌν•œ λ°©μ‹μœΌλ‘œ μž‘λ™ν•˜λŠ” κ±Έ μ•Œ 수 μžˆλ‹€.


✦ 좜처


🚨 ν•΄λ‹Ή ν¬μŠ€νŒ…μ€ Udemy의 ⌜React μ™„λ²½ κ°€μ΄λ“œβŒŸ κ°•μ˜λ₯Ό 베이슀둜 ν•œ κΈ°λ‘μž…λ‹ˆλ‹€.
✍🏻 κ°•μ˜ git repo λ°”λ‘œκ°€κΈ°

profile
일단 곡뢀가 '적성'에 λ§žλŠ” 개발자. κ·Όμ„±μžˆμŠ΅λ‹ˆλ‹€.

0개의 λŒ“κΈ€