내가쓴 부분은 1도 없고, 스파르타 항해99에서 제공해준 정보이다.
왜 Redux를 쓰는가?
- useState가 불편하기 때문이다.
- 여러 컴포넌트에서 같은 state를 공유해서 쓰려면 부모 자식 컴포넌트를 반드시 거쳐야 하는데, Redux를 사용해서 state를 중앙에서 관리하면 원하는 컴포넌트에서 바로 가져와서 사용 할 수 있다.
- 개발을 하면서 사용할 수 있는 devtools의 퀄리티가 좋고, 많은 개발자들이 사용하는 라이브러리라서 자료가 많아 error 해결이 용이하다.
리덕스 모듈 용어 정리
Action type
- 어떤 행동을 의미한다. 여기서 행동이란, 가령 계산기 기능을 구현한다면 plus, minus 처럼 기능에 필요한 행동을 뜻한다.
- action type은 object = {} 다. 그리고 무조건 type 이라는 key값을 가져야 한다.
// action type 1
{key: 'PLUS'}
// action type 2
{key: 'MINUS'}
- action type은 dispatch의 파라미터로 담겨 전송된다.
const dispatch = useDispatch();
//.. 중략
dispatch({type: 'PLUS'}) // PLUS action을 dispatch 했다.
InitialState
- 각각의 Reducer에서의 초기상태값 묶음 또는 초기값이다.
- reducer의 파라미터에서 default 값으로 넣어주도록 하자.
Action creator
- 뜻 그대로 action type을 만들어주는 함수입니다.
- 왜 굳이 함수를 사용해서 action type을 만드는 이유는, 만약 {type : ‘PLUS’} 라는 액션을 10개의 컴포넌트에서 dispatch 한다고 해볼게요. 그렇다면 10개의 컴포넌트에서 {type : ‘PLUS’} 라는 코드를 매번 하드 코딩해야 하는 불편함이 있고 또한 오타를 비롯한 예상치 못한 에러가 있을 수 있어요. 그래서 보통 {type : ‘PLUS’} 을 생성하는 함수를 통해 action type을 생성합니다.
- 코드로 확인하기
- // action creator export const plus = () => { return {type : 'PLUS'} } // action creator를 이용해서 dispatch 하기 dispatch(plus())
Reducer
- dispatch는 reducer에게 action을 전달해준다. reducer는 action을 보고 그 행동을 수행하여 새로운 state를 반환하는 역할을 한다. 마치 식당에서 주문서(action)를 받아 요리를 하여, 요리(state)를 내어주는 요리사와 비슷하다고 생각하면 된다.
- reducer은 조건문을 가진 함수 = function 이다. 또한 파라미터에서는 store의 state값과 disaptch가 전달해준 action을 받을 수 있다.
- 코드로 확인하기
- // 초기값 const initialState = 0; // 보통 switch문을 사용하여 reducer을 작성하곤 한다. const reducer = (state = initialState, action) => { switch(action.type){ case PLUS: return {...} case MINUS: return {...} default: return state } }
useDispatch
- react에서 redux를 사용하기 위해서는 react-redux라는 라이브러리를 같이 사용해야 한다. react-redux의 제공하는 리덕스 훅이다. function component 에서 리덕스를 쓰는 경우에는 useDispatch를 통해 간단하게 dispatch 할 수 있다.
<aside> 💡 redux는 react에서만 쓸 수 있는 기술이 아닙니다. 바닐라 JS, Vue 등 다른 환경에서도 사용 할 수 있는데, react-redux는 redux와 react를 이어주는 역할을 합니다.
</aside>
useSelect
- Store에 있는 상태 = 값 들을 꺼내올 때 사용합니다.
- const state = useSelector(state => state); console.log(state) // 무엇이 보이는지 콘솔에 찍어보세요!
코드로 보는 리덕스의 흐름
- 컴포넌트에서 dispatch를 실행
- 개발자(나)는 업데이트를 원하는 Store state가 있었을 때 action을 dispatch 한다.
- 코드로 확인하기
- // src/pages/Component.js import { useDispatch } from 'react-redux'; const Component = () => { const dispatch = useDispatch(); // 버튼을 누르면, PLUS 이라는 action type을 담아 dispatch 한다. const onClickHandler = () => { dispatch({type: 'PLUS'}); } return <button onClick={onClickHandler}>더하기 버튼</button> } export default Component;
- dispatch는 reducer에게 action을 전달
- dispatch를 통해 전달받은 action을 확인해보자.
- 코드로 확인하기
- // src/modules/calculate.js const initialState = 0; const reducer = (state = initialState, action) => { console.log(action) // {type: 'PLUS'}가 보인다. dispatch가 전달해준 것이다. switch(action.type){ case PLUS: return state + 1; case MINUS: return state - 1; default: return state } }
- reducer는 전달받은 action이 무엇인지 확인하고, 새로운 상태값을 반환
- action.type이 PLUS 인 것을 찾아 reducer는 기존 state값에 +1을 한 1 을 반환한다.
- store의 state값이 새로운 값으로 변경됨
- 반환된 1 이 store의 state 값으로 적용된다.
- 컴포넌트에서는 새로운 값을 useSelect을 통해 수신하고, 화면에 렌더링
- 이제 화면에서 새롭게 업데이트 된 store의 state 값을 가져와보자.
- 코드로 확인하기
- import { useDispatch, useSelector } from 'react-redux'; const Component = () => { const dispatch = useDispatch(); // redux에서 값을 가져올때는 useSelector를 사용한다. const number = useSelector(state => state.calculate); // 버튼을 누르면, PLUS 이라는 action type을 담아 dispatch 한다. const onClickHandler = () => { dispatch({type: 'PLUS'}); } return ( <> <div>{number}</div> {/* 가져온 값을 렌더링 해보자. */} <button onClick={onClickHandler}>더하기 버튼</button> </> ) } export default Component;
그래서, 뭐부터 해야 되나요?
modules 파일 만들기
- src 폴더에 “modules” 이라는 폴더를 만들어주세요. 폴더의 이름은 중요하지 않지만 보통은 modules 또는 “redux” 로 이름을 지어서 사용합니다.
(폴더 이름은 개발자 (나) 마음입니다 = 마음대로 하세요.)
설정하기
- 강의를 보고 설정을 해주세요. 설정은 처음에 한번 만 하면 됩니다. 그리고 설정을 하면서 작성하는 코드들이 이해가 되지 않아도 괜찮습니다. 왜냐하면, 이건 단지 설정 이기때문에 아직은 여러분들에게 중요한 코드들도 아니고, 이해를 할 필요도 없습니다. 이해 하려고 노력하지 마세요.
[중요 ‼️ ] ducks 패턴 파일 만들기
리덕스의 구성요소 action type, action creator, initialState, reducer를 작성하는게 리덕스 로직을 구현한다라고 해도 과언이 아닙니다. 우리가 redux에서 중점적으로 공부해야 할 것은 위 구성요소를 견고하고 정확하게 작성하는 방법 입니다.
- 계산기 기능에 대한 모듈 파일을 만들어볼까요?
- 구성요소를 작성해보세요.
- // src/modules/calculate.js // action type // 액션 타입을 생성하세요. // action creator // 액션 타입 생성 함수를 작성하세요. // initialState // 이 모듈의 초기값을 설정해주세요. // reducer // 리듀서를 만들어주세요. // 그리고 이 파일에서 export 하는 것은 reducer여야 합니다. export default reducer;
컴포넌트에서 dispatch, useSelector 하기
- dispatch, useSelect 로직을 작성해볼까요?
- 코드로 확인하기
- // src/pages/CalculateHome.js const CalculateHome = () => { return <div></div> } export default CalculateHome;
TIP
- 모듈 파일을 만드는 연습을 많이하세요. 비어있는 파일에서 아무 자료도 참고하지 않고 action type, action creator, reducer를 작성할 수 있을 때까지 연습하세요. 외우는 것도 방법입니다.
- 리덕스의 구성요소가 어떤 데이터 타입인지 반드시 기억하세요.
- action type은 type을 가진 객체다.
- reducer는 새로운 상태값을 반환하는 함수다.
- action creator는 action type을 반환하는 함수다.
- 설정 코드를 이해하려고 하지 마세요.
- 리덕스의 흐름을 그림으로 직접 그려보세요.
왜 미들웨어를 써야 하나요?
dispatch 하는 과정 안에서 개발자가 추가 동작을 하고 싶기 때문입니다. 만약 유저가 버튼을 눌렀을 때 3초 후에 +1이 되는 기능을 만드는 개발자라고 가정해볼게요. 아마 아래의 과정이 필요할 거에요.
1. button 클릭한다. = dispatch(plus())
2. 3초를 기다린다.
3. +1를 더한다.
하지만 미들웨어를 쓰지 않은 리덕스에서는 3초를 기다린다 라는 동작을 할 수 없어요. dispatch를 하는 즉시 reducer에 action type을 건네주기 때문이죠. 이렇게 무언가 리덕스의 흐름에서 개발자가 추가로 어떤 동작을 하고자 할 때 미들웨어를 사용합니다. 그리고 보통 추가동작 이라고 한다면, ‘서버와의 통신’ 이라는 동작일 확률이 가장 높습니다.
Redux-thunk
리덕스의 미들웨어에는 여러가지 있는데, 그 중 이번 프로젝트에서 사용할 것은 Redux-thunk 입니다. 이것을 사용하면 무엇이 가능해지냐면 dispatch()에 인자에 action type 객체가 아닌 함수를 넣을 수 있게 됩니다.
<aside> ‼️ 기본 리덕스에서 dispatch()는 인자에는 반드시 action type 객체가 들어가야만 합니다.
</aside>
하지만, redux-thunk를 사용하는 순간부터는 함수 가 들어갈 수 있습니다. 우리는 그 함수를 thunk 함수라고 부릅니다. 그리고 우리 개발자들은 ‘추가동작'을 이 thunk 함수 안에다가 구현하면 됩니다. 모든 추가 동작이 끝나면 원래 하고자 했던 dispatch를 다시 해서 reducer를 작동시킵니다.
Redux-thunk를 사용했을 때 흐름을 볼까요?
- dispatch(Thunk function)
- thunk function 실행되고, 개발자가 작성한 추가동작들이 실행
- dispatch(action type)
- Reducer가 action type을 전달받아 새로운 상태값을 반환합니다.
Thunk Function
thunk 함수는 이렇게 생겼습니다. 함수를 반환하는 함수 입니다. 이러한 함수를 고차함수라고 부릅니다. 다만 지금 당장은 이 고차함수의 원리보다도 thunk 함수를 생성하고 사용하는 방법에 집중해봅시다.
const thunkFunction = (args) => (dispatch, getState) => {
// 추가동작 구현
// 하고자 했던 action type dispatch
dispatch(plus())
};
이렇게, redux-thunk 를 사용하여 thunk 함수를 생성, 추가 동작을 할 수 있습니다. 우리는 보통 서버와의 통신을 이 thunk 함수 안에서 하게 될 것입니다.
'Web > React' 카테고리의 다른 글
React Redux (0) | 2022.05.27 |
---|---|
명령형 vs 선언형 프로그래밍 (0) | 2022.05.27 |
React - Redux Toolkit (0) | 2022.05.26 |
React - Redux (0) | 2022.05.26 |
React - Github IO (0) | 2022.05.22 |