useState가 있기 대문에 useReducer를 사용하는 이유를 몰랐다. useState로 관리를 하면 된다고 생각했기 때문에, 늘어나는 useState를 보면서 "이게 맞나?" 하는 의문이 들때도.
그런데, 팀원분들과 코드리뷰를 하면서 useReducer를 모듈화 하신 분이 계셔서 관심을 갖고 사용해보려고 했다.
내가 생각하는 useReducer를 사용하는 이유
useState가 많아지는 상황이라면 사용을 고려할 수 있다. 모듈화를 통해 코드를 분리하여 재사용이 가능하다.
useReducer에서 reducer를 모듈화 하기 위한 방법을 이전부터 고민하긴 했다.
검색했을 때 보통의 예시는 increase와 decrease에 대한 정석 코드.
처음에는 코드를 기억했다.
1. 구조는 useState와 똑같고
2. const ['상태(객체)', '함수'] = useReducer('함수', '상태(객체)') 이런 구조를 갖고 있었으며 reduce '함수'도 action이라는 '객체'의 프로퍼티를 통해 어떤 동작을 할지 결정한다는 것
3. 그리고 dispatch('객체')
이런 대략적인 구조로 '객체', '함수'를 이용한다는 것
const [state, dispatch] = useReducer(reduce ,initialState)
const reduce(state,action) {
switch(action.type){
case x:
return 상태 업데이트 로직
case y:
return 상태 업데이트 로직
case z:
return 상태 업데이트 로직
default:
return state
}
}
useReduce할 때 처음 접하는 increase, decrease 예시처럼 initialState가 0이거나 단 하나의 state만 관리를 한다면 크게 헷갈리는 부분은 없다. 그래서 처음에 'useState를 쓰면 편한데 왜 굳이 useReducer를 써야하는 걸까?' 하고는 모듈화 정도의 코드 암기만 하고 사용해본적은 없었다.
그런데 중요한건, initialState가 객체 형태이며 프로퍼티가 여러 개 일 때 진지하게 생각해봐야 한다.
즉, useState로 관리하는 상태가 여러개이면서 비슷한 동작을 할 때!
예를들어 입력받는 input이 여러개인 경우. 심지어 모듈화도 가능하다. 최고!
이제부터는 useRuduce를 적용하면서 비롯된 의문과 나름대로 이해한 내용
1. 상태 관리 로직인데, state 변수와 initialState는 .. 어떻게 사용되는 걸까
=> state: reduce 함수 내에서 상태 업데이트에 관여한다.
=> initialState: 초기화 객체/변수. 딱 한번만 초기화할 때 사용된다.
2. state를 업데이트할 때는 setState할때와 마찬가지로 state 전체를 업데이트 해야 한다.
=> setState라면
setState({...state, [state의 프로퍼티]: action.[action의 프로퍼티]})
useReducer에서는
return {...state, [state의 프로퍼티]: action.[action의 프로퍼티]}
3. TypeScript에서는 state에 대한 type, action에 대한 type을 지정해주면 된다.
=> state에 대한 타입은 객체 안에 들어가는 프로퍼티에 대한 타입.
=> 문제는, action에 대한 타입인데.
(1) action 객체는 { type, payload(혹은 value) }구조라고 생각한다.
=> 그렇다면 payload는 도대체 뭐지? 싶었는데, 그냥 내가 보내주고 싶은 데이터이다. 그러니까, state상태를 변화하게 만드는 값. 예를들어 state +1이면 1이 payload(혹은 value) 이다.
물론 다음처럼 switch- case 구문 내에서 직접 state에 조작을 가할수도 있다.
switch (action.type) {
case 'INCREASE':
return state + 1;
...
}
그렇지만, 좀 더 의존성을 줄여본다면 action 객체가 payload(혹은 value)를 갖게 하는 게 좋은 것 같다.
내가 고민한 경우는 <input>의 onChange 함수를 사용해서 input 안의 value를 바꾸고 싶은데, 어떻게 하지?! 였다.
첫번째: onChange에 전달할 함수가 필요했다.
두번째: 값을.. 어떻게.. 전달하지? 였는데, 침착하게 생각해보면 e.target.value를 사용하는 것은 변함이 없다. 단지 이것을 이용해서 어떻게 state를 변화시키는지 헷갈렸다.
결과적으로는 dispatch로 action 객체를 전달하면 된다.
(e: React.ChangeEvent<HTMLInputElement>) =>
dispatch({ type: 'email', payload: e.target.value }
(payload:데이터. 구글링하면 value대신 접할 수 있는 단어가 payload여서 혹시라도 헷갈릴까봐 payload라는 단어를 계속 사용했다. value랑 같다!)
4. 모듈화를 하면 좋은 점
- 뷰 페이지에 대한 코드가 적어진다.
- 전역적 관리도 가능할 것 같다. (모듈 내에 초기화가 이루어진다면..?) -> 안해봄
- 재사용성 -> 안해봄
'Front-End > React.js' 카테고리의 다른 글
컴포넌트 리렌더링 방지하기! React.memo (0) | 2023.03.06 |
---|---|
useCallback, useMemo 활용해보기 (0) | 2023.03.06 |
커스텀 Hooks (0) | 2023.03.06 |
리액트 프로젝트 진행시 고민하는 부분 (0) | 2023.03.03 |
(책) 리액트를 다루는 기술 (0) | 2023.01.13 |