본문 바로가기

Study/React

useReducer

what is useReducer? 

reducer는 state 관리를 돕는 훅으로, useState와 비슷하다. 대신 useState보다 더 많은 기능을 가지고 있기 때문에, 복잡한 state를 관리할 때에는 state 대신 reducer를 사용한다. 복잡한 state란 어떤 state일까? 

 

  1. 어떤 state의 업데이트가 다른 state에 의존하고 있다(그래서 최신 state를 보장받을 수 없을 때).
  2. 서로 연관있는 state가 여러 개 존재하고 있다(action 객체 데이터나, state를 객체로 관리해서 하나의 state로 관리 가능). 
  1.  

How to use Reducer?

const [state, dispatchFn] = useReducer(reducerFn, initialState, initFn)

 

  1. state | 가장 최신의 state, useState의 state와 같음
  2. dispatchFn | 새로운 action을 dispatch(=send) 하는 함수
    1. dispatch(action) 
    2. action은 보통 객체 데이터로, 어떤 데이터를 보낼 것인지 코드로 설정할 수 있다. 
  3. reducerFn | dispatchFn이 action을 보내면(dispatch가 실행되면) 호출되는 함수
    1. (prevState, action) => { return newState }
    2. 업데이트 된 state를 반환해야 한다. 
    3. useState이 콜백함수를 전달받을 때의 확장된 버전이라고 볼 수 있다(prev => { }). 

어떤 state가 다른 state에 의존하고 있을 때 

const Login = (props) => {
  const emailChangeHandler = (event) => {
    setEnteredEmail(event.target.value);
    setFormIsValid(
      event.target.value.includes('@') && enteredPassword.trim().length > 6
    ) 
  };

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

 

  1. 두 changeHandler 함수는 form 유효성 상태를 업데이트 하고 있다.
  2. form 유효성 상태는 다른 state(entered input)를 기반으로 업데이트 된다. 
  3. 이 때 entered input의 state가 가장 최신의 state임을 보장할 수 없다. 
    • 어떤 state를 업데이트 할 때, set의 콜백 함수 인자로  state의 prevState를 전달할 수 있다.
    • 예를 들어 댓글 리스트를 업데이트 한다고 하자. 이전의 모든 댓글 리스트(prevState)를 받아와서, 그 리스트에 새로운 아이템을 더하는 형식으로 업데이트할 것이다. 
    • 그러나 form 유효성 업데이트 함수는 자기 자신의 prevState가 아니라, 다른 state(enterd input)에 의존하고 있다.
    • 콜백의 인자로는 자기 자신의 prevState 만을 전달할 수 있으므로, entered input의 prevState는 인자로 전달할 수 없다. 즉 entered input의 가장 최신 state를 보장받을 수 없다. 

연관있는 여러 state가 존재할 때

useState

const [emailInput, setEmailInput] = useState({ value: '', isValid: null });
const emailChangeHandler = (event) => {
    setEmailInput({
      value: event.target.value,
      isValid: event.target.value.includes('@'),
    });
};

const validateEmailHandler = () => {
    setEmailInput((prev) => { ...prev });
};

useReducer

const [pwInput, dispatchPwInput] = useReducer(
    // reducer 
    (prev, action) => {
      if (action.type === 'USER_INPUT') {
        return { ...prev, value: action.value, isValid: action.value.includes('@') };
      }
      if (action.type === 'INPUT_BLUR') {
        return { ...prev, isFocused: true };
      }
      if (action.type === 'RESET') {
        return { value: '', isValid: null };
      }
    },
    // initial state
    { value: '', isValid: null }
);

const passwordChangeHandler = (event) => {
    dispatchPwInput({ // action 
      type: 'USER_INPUT',
      value: event.target.value,
    });
};

const passwordBlurHandler = () => {
    dispatchPwInput({ type: 'INPUT_BLUR' });
};

 

'Study > React' 카테고리의 다른 글

Rules of Hooks  (0) 2022.06.20
useContext  (0) 2022.06.20
useEffect  (0) 2022.06.19
useRef  (0) 2022.06.18
Fragment & Portal  (0) 2022.06.18