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
κ³Ό λμΌν λ°©μμΌλ‘ μλνλ κ±Έ μ μ μλ€.useInput
컀μ€ν
ν
λ΄λΆμ input μν(state)λ₯Ό useReducerλ‘ κ΄λ¦¬νκΈ°useInput
컀μ€ν
ν
μ λ‘μ§λ€μ 보면, μν(state) κ°λ€μ΄ λ€μνμ§λ μκ³ , μ
λ°μ΄νΈ λ‘μ§μ΄ λ±ν 볡μ‘ν κ²μ μλλ€. κ·Έλλ κ·Έκ° κ³΅λΆν΄μ¨ useReducer
λ₯Ό μ°μ΅νκΈ° μν΄μ useInput
λ΄λΆμμ useState
λμ useReducer
λ₯Ό ν λ² μ¬μ©ν΄λ³Ό κ²μ΄λ€.const [enteredValue, setEnteredValue] = useState("");
const [isTouched, setIsTouched] = useState(false);
useReucer
λ‘ κ΄λ¦¬νλ €λ©΄ μ΄λ»κ² ν΄μΌ ν κΉ? λ¨Όμ useReducer
λ₯Ό import λΆν° ν΄μ€μ.import { useReducer } from "react";
useReducer
λ₯Ό νΈμΆνκΈ° μ μ λ¨Όμ 리λμ μ μ© ν¨μλ₯Ό λ§λ λ€. μ΄λ¦μ inputStateReducer
μ΄λ€.const inputStateReducer = (state, action) => {};
const inputStateReducer = (state, action) => {
return {
value: "",
isTouched: false,
};
};
...
// const [enteredValue, setEnteredValue] = useState("");
// const [isTouched, setIsTouched] = useState(false);
useState
λ‘ κ΄λ¦¬ν΄μ£Όμλ λκ°μ μν(state) κ°μΈ enteredValue
μ isTouched
μ μ΄κΈ° κ°μ μ΄μ κ³Ό λμΌνκ² μ€μ ν΄μ€λ€.useReducer();
useInput
λ΄λΆμμ useReducer
λ₯Ό νΈμΆν΄μ£Όκ³ ,useReducer(inputStateReducer);
inputStateReducer
λ₯Ό 첫 λ²μ§Έ μΈμλ‘ μ λ¬ν΄μ€λ€. κ·Έλ¦¬κ³ , useInput
ν¨μ λ°κΉ₯μ initialInputState
λΌλ μμλ₯Ό μμ±ν΄μ£Όκ³ ,const initialInputState = {
value: "",
isTouched: false,
};
inputStateReducer
μμ μ΅μ’
μ μΌλ‘ λ°ννλ μ΄κΈ° μν κ°μ²΄ κ°μ ν λΉν΄μ€λ€. κ°μ²΄ κ°μ μμλ‘ ν λΉνμΌλ, κ΅³μ΄ λ¦¬λμ ν¨μμμ κ°μ κ°μ²΄ κ°μ λ°νν νμλ μμ κ²μ΄λ€. κ·Έλ¬λ, κ°μ²΄ λμ inputStateReducer
μμλ₯Ό λ°ννλλ‘ νλ€.const inputStateReducer = (state, action) => {
return inputStateReducer;
};
useReducer
μ λ λ²μ§Έ μΈμλ‘ initialInputState
μμλ₯Ό μΆκ°νλ€.useReducer(inputStateReducer, initialInputState);
useState
μ²λΌ useReducer
ν¨μλ μ νν λ μμλ₯Ό κ°μ§ λ°°μ΄λ‘ λ°νν μ μλλ‘ λ°°μ΄ κ΅¬μ‘° λΆν΄ ν λΉμΌλ‘ μ²λ¦¬νλ€.const [inputState, dispatch] = useReducer(inputStateReducer, initialInputState);
inputState
λ 리λμ ν¨μμ μν΄ κ²°μ λλ μν(state)μ¬μΌ νλ©°, λ λ²μ§Έ μμμΈ dispatch
λ λμ€ν¨μΉ ν¨μλ‘, 리λμ ν¨μμμ μ€νν ν¨μμ λν μμμ΄λ€. μ΄μ κ°μ κ²μ¦ν λ enteredValue
μν κ° λμ , inputState.value
λ‘ λ체ν΄μ μ¬μ©ν μ μκ² λμλ€.
inputState
μμvalue
λ‘ μ κ·Όν μ μλ μ΄μ λ,inputState
μ ꡬ쑰λinitialInputState
μ λμΌνκΈ°μinputState
λ λ§μ°¬κ°μ§λ‘value
λΌλ μμ±μ κ°κ² λκΈ° λλ¬Έμ΄λ€. λ¬Όλ‘ ,value
μ²λΌisTouched
λinputState.isTouched
λ‘ μ κ·Όν μ μλ€.
useState
λ‘ μ¬μ©νλ λ‘μ§λ€μ μ λΆ λ³κ²½ν΄μ€λ€.// const valueIsValid = validateValue(enteredValue);
// const hasError = !valueIsValid && isTouched;
const valueIsValid = validateValue(inputState.value);
const hasError = !valueIsValid && inputState.isTouched;
const valueChangeHandler = (event) => {
setEnteredValue(event.target.value);
};
valueChangeHandler
μ΄λ²€νΈ ν¨μ λ΄λΆμ μλ setState
μ
λ°μ΄νΈ ν¨μλ₯Ό μ§μ°κ³ ,const valueChangeHandler = (event) => {
// setEnteredValue(event.target.value);
dispatch();
};
dispatch
ν¨μλ₯Ό νΈμΆν΄μ 리λμμκ² μ€νν μμ
μ λμ€ν¨μΉ νλλ‘ νλ€. 보ν΅μ κ°μ²΄ λ΄λΆμ type
μμ±μΌλ‘ μμ
μ μ ν΄μ£ΌκΈ° λλ¬Έμ, type
μμ±μ μ κ³ , λ΄λΆμ "INPUT" μ΄λΌλ κ°μ μ§μ νλ€.const valueChangeHandler = (event) => {
dispatch({ type: "INPUT" });
};
value
μμ±μ μΆκ°νκ³ , λ΄λΆμ event.target.value
λ₯Ό κ°μΌλ‘ ν λΉν΄μ€λ€.const valueChangeHandler = (event) => {
dispatch({ type: "INPUT", value: event.target.value });
};
const inputBlurHandler = () => {
// setIsTouched(true);
dispatch({ type: "BLUR" });
};
const reset = () => {
// setEnteredValue("");
// setIsTouched(false);
dispatch({ type: "RESET" });
};
-inputBlurHandler
μμλ value
μ λν΄μλ μ€μ ν΄μ€ νμκ° μμΌλ type : "BLUR"
λ§ μΆκ°νκ³ , reset
ν¨μ μμ type : "RESET"
μ΄ λ΄κΈ΄ κ°μ²΄λ₯Ό dispatch
ν¨μμ μ λ¬νλ€.
return {
// value: enteredValue,
// isValid: valueIsValid,
value: initialInputState.value,
isValid: valueIsValid,
hasError: hasError,
valueChangeHandler: valueChangeHandler,
inputBlurHandler: inputBlurHandler,
reset: reset,
};
useInput
μ΄ λ°ννλ κ° μ€μ value
λ₯Ό enteredValue
κ° μλ, initialInputState.value
λ‘ μμ ν΄μ€λ€.dispatch
λ‘ μ λ¬ν μΈ κ°μ§ type("INPUT", "BLUR", "RESET")μ λν κ°κ°μ μμ
λ΄μ©μ 리λμ ν¨μ λ΄λΆμμ μ€μ ν΄μ£Όλ©΄ λλ€.const inputStateReducer = (state, action) => {
if (action.type === "INPUT") {
}
if (action.type === "BLUR") {
}
if (action.type === "RESET") {
}
return inputStateReducer;
};
action.type
μ΄ "INPUT" μΌ λλ μ΅μ’
μ μΌλ‘ μλ‘μ΄ μν κ°μ²΄μμ valueμ κ°μ action.value
λ‘ μ ν΄μ£Όλλ‘ νλ€.const inputStateReducer = (state, action) => {
if (action.type === "INPUT") {
return {};
}
if (action.type === "BLUR") {
}
if (action.type === "RESET") {
}
return inputStateReducer;
};
value
μ μμ±κ³Ό κ°μ μ§μ νλ€. μ΄λ value
λΌλ μμ±μ΄ "INPUT" νμ
μΌ λ event.target.value
λ‘ λ겨 λ°μ κ°μ΄ μκΈ° λλ¬Έμ κ°λ₯ν κ²μ΄λ€. isTouched
λ ν€λ₯Ό μ
λ ₯μ λ§μΉ λμλ§ true μ΄μ΄μΌ νκΈ° λλ¬Έμ, μ΄κΈ° μν(false)μΈ state.isTouched
λ₯Ό κ·Έλλ‘ λ겨μ€λ€.const inputStateReducer = (state, action) => {
if (action.type === "INPUT") {
return { value: action.value, isTouched: state.isTouched };
}
if (action.type === "BLUR") {
return {};
}
if (action.type === "RESET") {
}
return inputStateReducer;
};
action.type
μ΄ "BLUR" μΌ κ²½μ°μλ μ΄λ¨κΉ? μ¬μ©μκ° input μ°½μ ν΄λ¦νκ³ ν¬μ»€μ€λ₯Ό μμμ λμλ§ μλνκ² λλ€. μμ μλ‘μ΄ μν κ°μ²΄λ₯Ό λ°ννκ³ , isTouched
μ true κ°μ μ λ¬νλ€. μ΄λ value
μλ κ΄λ ¨μ΄ μκΈ° λλ¬Έμ, μ΄κΈ° μνμΈ state.value
λ₯Ό κ·Έλλ‘ λ겨μ€λ€.const inputStateReducer = (state, action) => {
if (action.type === "INPUT") {
return { value: action.value, isTouched: state.isTouched };
}
if (action.type === "BLUR") {
return { isTouched: true, value: state.value };
}
if (action.type === "RESET") {
return {};
}
return inputStateReducer;
};
actin.type
μ΄ "RESET"μΌ λμλ λ§ κ·Έλλ‘ κ°μ μ΄κΈ°νν΄μ£Όλ νΌν¬λ¨Όμ€λ₯Ό 보μ¬μΌ νλ€. isTouched
λ₯Ό λ€μ μ΄κΈ° μν κ°μΈ falseλ‘ μ€μ νκ³ , value μμ μ΄κΈ° μνμΈ λΉ λ¬Έμμ΄ "" μΌλ‘ μ€μ νκ³ κ°μ²΄λ‘ λ΄μμ λ°νν μ μλλ‘ ν΄μ€λ€.const inputStateReducer = (state, action) => {
if (action.type === "INPUT") {
return { value: action.value, isTouched: state.isTouched };
}
if (action.type === "BLUR") {
return { isTouched: true, value: state.value };
}
if (action.type === "RESET") {
return { isTouched: false, value: "" };
}
return inputStateReducer;
};
useReducer
λ₯Ό μ¬μ©ν νμλ μμμ§λ§, κ·Έκ° κ³΅λΆν΄μ¨ λΆλΆμ 볡μ΅νμλ μλ―Έμμ ν΄λΉ 컀μ€ν
ν
μ μν κ°λ€μ useState
λμ useReducer
λ₯Ό μ μ©ν΄λ³΄μλ€. νμ€ν μ΄μ λ³΄λ€ μ΄ν΄λ₯Ό κΈ°λ°μΌλ‘ ν νμ©μ μΈ‘λ©΄μμ μ€λ ₯μ΄ ν₯μλμμμ λλ μ μμλ€. λν, μ΄λ² μΉμ
μ ν΅ν΄μ form μ μμ±νκ³ κ°μ λ°μμ€λ κ²μ΄ μκ°λ³΄λ€ 볡μ‘νκ³ μ΄λ €μ΄ μΌμμ μκ² λμκ³ , κ°κ°μ input μν κ°λ§λ€ μ ν¨μ± κ²μ¦μ λ°μ Έ μ μ΄λ₯Ό νλ κ²μλ μμΉ« μλͺ»νλ€κ° 볡μ‘ν λ‘μ§μ μμ±ν μλ μλ€λ κ²μ μ μ μμλ€. μ§κΈμ λΉλ‘ κ°μμ λ°λ₯Έ μ°μ΅μ κ°κΉμ§λ§ μ΄νμ μ€λ¬΄μμλ λ°°μ΄ λ΄μ©μ μ κ·Ήμ μΌλ‘ μ¬μ©ν μ μμΌλ¦¬λΌλ κΈ°λλ₯Ό κ°κ² λμλ€.π¨ ν΄λΉ ν¬μ€ν μ Udemyμ βReact μλ²½ κ°μ΄λβ κ°μλ₯Ό λ² μ΄μ€λ‘ ν κΈ°λ‘μ λλ€.
βπ» κ°μ git repo λ°λ‘κ°κΈ°