useReducer

2JE0·2022년 1월 26일
0

React

목록 보기
11/17
post-thumbnail

useReducer

다음과 같은 앱의 validity를 확인할 때, useState를 사용하면 문제점이 발생 할 수도있다. 아래의 다섯가지 상태에 의존한다. enteredEmail은 입력받은 값이고 emailIsValid는 이메일의 유효성을 검증하는 상태이다.

  const [enteredEmail, setEnteredEmail] = useState('');
  const [emailIsValid, setEmailIsValid] = useState();
  const [enteredPassword, setEnteredPassword] = useState('');
  const [passwordIsValid, setPasswordIsValid] = useState();
  const [formIsValid, setFormIsValid] = useState(false);

그런데 이메일이 변했을 때, 유효성을 검증하려면 password state의 정보도 필요하기 때문에 이전상태에 의존한 업데이트를 해야한다. 이것은 문제를 일으킬 수도 있다. emailIsValidenteredEmail에 의존하기 때문이다.

 const emailChangeHandler = (event) => {
    setEnteredEmail(event.target.value);

    setFormIsValid(
      event.target.value.includes('@') && enteredPassword.trim().length > 6
    );
  };
const validateEmailHandler = () => {
    setEmailIsValid(enteredEmail.includes('@'));
  };

useReducer 사용하기

그래서 useReducer이라는 훅을 사용할 것인데, useReducer 복수의 상태를 한번에 업데이트 할 수 있다.

  • import { useReducer } from "react";

  • 초기 상태를 넣어준다.

  const [emailState, dispatchEmail] = useReducer(emailReducer, {
    value: "",
    isValid: null,
  });
  • email이 변했을때 작동하는 함수에 dispatch를 넣어준다.
const emailChangeHandler = (event) => {
    dispatchEmail({ type: "USER_INPUT", value: event.target.value });
    setFormIsValid(event.target.value.includes("@") && passwordState.isValid);
  };
  • reducerFn을 정의해 준다.
const emailReducer = (state, action) => {
  if (action.type === "USER_INPUT") {
    return { value: action.value, isValid: action.value.includes("@") };
  }
  if (action.type === 'INPUT_BLUR') {
    return {value: state.value, isValid: state.isValid}
  }
  return { value: "", isValid: false };
};

그렇다면 이제 emailState.value로 값을, emailState.isValid로 유효성을 검증 할 수 있다.


useEffect와 결합

  useEffect(() => {
    const identifier = setTimeout(() => {
      console.log("Checking form validity!");
      setFormIsValid(emailState.isValid && passwordState.isValid);
    }, 500);

    return () => {
      console.log("CLEANUP");
      clearTimeout(identifier);
    };
  }, [emailState, passwordState]);

이전에 useEffect 를 이용해서 유효성 검증에 너무 많은 요청을 보내지 않도록 했었다. 그런데 예를들어, 패스워드를 6글자 이상 입력해야 하지만 7글자에서 더 추가한다고 해서 유효성이 바뀌지 않는다.

따라서 상태에 따라서 유효성을 검증할 것이 아닌, 유효성이 변할 때만 useEffect를 사용하도록 하자.


다음과 같이 구조분해를 먼저 사용해서 emailState안에 있는 isValid라는 변수를 emailIsValid라고 쓰기로 한다.

  const { isValid: emailIsValid } = emailState;
  const { isValid: passwordIsValid } = passwordState;
 useEffect(() => {
    const identifier = setTimeout(() => {
      console.log("Checking form validity!");
      setFormIsValid(emailState.isValid && passwordState.isValid);
    }, 500);

    return () => {
      console.log("CLEANUP");
      clearTimeout(identifier);
    };
  }, [emailIsValid, passwordIsValid]);

의문점

useEffect(()=>{},[emailState.isValid, passwordState.isValid]) 로 쓰면 안되나..?

중첩 속성을 useEffect에 종속성으로 추가하기

이전 강의에서 우리는 useEffect()에 객체 속성을 종속성으로 추가하기 위해 dstructuring을 사용했습니다.

const { someProperty } = someObject;
useEffect(() => {
  // code that only uses someProperty ...
}, [someProperty]);

이것은 매우 일반적인 패턴 및 접근 방식이며, 이것이 제가 일반적으로 이 방식을 사용하는 이유이며 여기서 보여드리는 이유입니다(코스 내내 계속 사용할 것입니다).

핵심은 우리가 destructuring을 사용한다는 것이 아니라, 전체 개체 대신 특정 속성을 종속성으로 전달한다는 것입니다.
우리는 이와 같이 코드를 작성할 수도 있으며 같은 방식으로 작동합니다.

useEffect(() => {
  // code that only uses someProperty ...
}, [someObject.someProperty]);

이것은 잘 작동합니다!

하지만 여러분은 이 코드 사용을 피해야 합니다:

useEffect(() => {
  // code that only uses someProperty ...
}, [someObject]);

왜 그럴까요?

왜냐하면 effect 함수는 someObject 가 변경될 때마다 재실행되기 때문이죠 - 단일 속성이 아닙니다 (someProperty 위의 예에서)

0개의 댓글

관련 채용 정보