일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- Code States
- HTML5문서
- CSS Object Model
- github
- 프로그래머스
- CSS 박스모델
- history API
- 깃허브
- flex box
- BOM
- block 박스
- Til
- 스코프
- 오블완
- overflow: hidden
- placeholder
- 코드스테이츠
- section태그와 article태그의 차이점
- HTML요소
- 객체지향프로그래밍
- 외계행성의 나이
- display와 visibility
- Scope
- 템플릿 문자열
- opacity
- 시맨틱
- javascript
- GIT
- 티스토리챌린지
- CSS 스타일
- Today
- Total
해말그미의 코딩공부
Redux 본문
Redux는 상태관리 라이브러리이다
🌷 왜 씀?? => props 문법 귀찮을 때
리액트는 html 안에다가 컴포넌트를 구성요소와 작동방식 복붙하는 식으로 개발을 한다.
여기서 컴포넌트는 <div></div> 뱉는 함수 이런거다. 원하는 곳에 복붙하는 형식으로 웹 개발을 한다.
변수를 다른 컴포넌트에서 쓰려면 props문법으로 전송해줘야 쓸 수 있었다.
하위 컴포넌트가 엄청~ 많다면 전송할게 넘 많아진다. 이럴 때 Redux 를 쓴다.
따로 저장하기 때문에 props가 필요없고 코드가 짧아진다.
또 상태관리가 용이하다. 즉 state 관리가 용이하다는 것이다.
컴포넌트는 state 직접 수정하지 않고 store.js에게 수정해 달라고 요청만 하는 것이다.
버그가 일어나도 store.js에서 잘못된 것이기 때문에 추적이 용이하다.
이것을 Reducer 라고 부른다. => state 수정과 꺼내쓰는 것.
컴포넌트에서 state 수정요청하려면?? => dispatch 함수를 쓴다.
흐름은 아래에 나와 있다.
🌷 Redux는 다음과 같은 순서로 상태를 관리합니다.
- 상태가 변경되어야 하는 이벤트가 발생하면, 변경될 상태에 대한 정보가 담긴 Action 객체가 생성됩니다.
- 이 Action 객체는 Dispatch 함수의 인자로 전달됩니다.
- Dispatch 함수는 Action 객체를 Reducer 함수로 전달해 줍니다.
- Reducer 함수는 Action 객체의 값을 확인하고, 그 값에 따라 전역 상태 저장소 Store의 상태를 변경합니다.
- 상태가 변경되면, React는 화면을 다시 렌더링 합니다.
즉, Redux에서는 Action → Dispatch → Reducer → Store 순서로 데이터가 단방향으로 흐르게 됩니다.
🌷 <리덕스 동작하는 흐름 >
'어떤 흐름을 통해 우리의 애플리케이션에 기여를 하는가'를 알면 된다.
store는 정보가 저장되는 곳이다. 실제 정보는 state에 저장된다. 우리가 직접 state 에 접근하는 것은 불가능하다. 항상 누군가를 통해 가능하다.
store를 만들 때 reducer 라는 함수를 만들어서 공급해줘야 한다.
=> 우리는 이것을 작성하는 것이 redux를 만드는 일이라고 해도 될 정도로 중요한 역할을 하는 것이 reducer
render 은 redux랑 상관없이 우리의 코드란 얘기이다. UI를 만들어줄 우리가 짤 코드이다.
state 값은 직접 가져올 수 없다. store를 은행이라고 한다면 은행직원을 통해 가져올 수 있다.
store.getState(); 를 해서 state 값을 가져온다.
render은 내부적으로 store 에서 데이터를 가져오고 getState는 state 값을 가져오고 render에게 주는 것이다.
우리가 직접 가져오면 망가뜨리기 때문에 금지한 것이다.
render 는 state값을 반영해서 UI 를 만든다.
state값이 바뀔 때마다 render 함수를 호출 할 수 있다면 UI가 바뀔 때 너무 좋지 않을까?
state값이 바뀔 때마다 render 갱신 할 수 있는 것 => subscribe
우리의 render함수를 subscribe에 등록하는 코드는
하면 state가 바뀔 때마다 render함수가 호출되면서 UI가 새롭게 갱신된다.
새로운 것을 생성한다면??
dispatch는 reducer를호출해서 state 값을 바꾼다.
subscribe 이용해서 render를 호출한다.
dispatch가 reducer를 호출할 때 두개의 값을 전달
현재 state, action data(객체)
위 코드를 보면 state를 입력값으로 받고, action을 참조해서 => 새로운 state값을 만들어서 return 해주는 state 가공하는 가공자이다.
=> 즉, reducer가 return 하는 값이 새로운 state가 된다.
핵심은 state를 기반으로 render 화면에 그려주고, state에 직접 접근하는 것이 금지되어 있기 때문에
getState를 통해 값을 가져오고 dispatch를 통해 값을 변경시키고 subscribe를 통해 값이 변경 됐을 때 구동될 함수들을 등록해준다. reducer 를 통해 state값을 변경한다.
🌷 <Redux의 적용 : Store 생성>
store를 만들면 state가 기본적으로 생기고 state값을 가져오려면 getState를 사용해야 한다.
그리고 reducer를 통해 state 값을 만들어 줘야 하는데
reducer의 기존 state 값이 undefiend라면 그것은 초기화를 위해 최초로 실행되는 reducer의 호출이기 때문에 원하는 값을 return 해주면 redux의 store에 초기값이 설정이 된다.
🌷 <Redux의 적용 : reducer와 action을 이용해서 새로운 state 값 만들기>
위의 두개를 봤을 때 콘솔에 찍어보면
{color : "yellow"}
{type : "CHANGE_COLOR", color :"red"}로 나오는 것을 알 수 있다.
store.dispatch({type:'CHANGE_COLOR', color:'red'});
에서 dispatch 호출하면 reducer를 호출하도록 약속되어 있고, 그러면 이전의 state값과 전달된 action을 인자로 준다.
이렇게 주면 얘가 state값으로 교체가 된다.
store.getState() 를 콘솔에 해보면
{color :"red"}가 나온다.
정리 : reducer는 이전의 state와 action을 받아서 다음의 state 값을 리턴해 주는 친구이다.
return {color :'red'} 대신 아래와 같이 써도 되나 그건 추천하지 않는다!
이유는 위와 같은 코드는 state 값을 변경해서 return 하는 방식이고
state 값을 복제하고 복제된 복사본을 변경한다음 리턴해야 시간여행 undo, redo와 같은 것을 할 수 있고 애플리케이션을예측가능하게 동작할 수 있게 한다. => Reducer의 Immutability(불변성)을 참고하면 된다.
=> Redux의 장점 중 하나인 변경된 state를 로그로 남기기 위해서 꼭 필요한 작업이다.
객체를 복사할 때에는 object.assign();라는 명령을 이용하면 된다.
첫 번째 인자 : 빈객체
두 번째 인자 : 복제할 속성을 가진 객체
예를 들어
이면
와 같이 새로운 객체가 복사된다.
위의 내용을 이렇게 바꿀 수 있다.
변수를 선언하고, 그 값은 첫번째로 빈객체, 두번째로 state를 주면 state 의 property들이 빈객체에 복제되서 리턴된다.
세번째도 복제된다. 그리고 그것을 리턴한다.
=> 이 방식은 state를 복제하고 복제한 것의 컬러를 레드로 준 값을 리턴하는 것이다.
reducer가 실행될 때 마다 return 되는 값이 새로운 state가 되는데 각각의 state가 독립된 복제된 결과들이 리턴되야 한다.
=> store의 state 값을 변경해준다
어떻게 action 값과 이전의 state값을 이용해서 새로운 값을 리턴해주면, 그 리턴값이 새로운 state값이 되고
그 리턴값은 원본을 바꾸는게 아니라 이전의 값을 복제한 것을 리턴해야지만 리덕스를 효과적으로 사용할 수 있다.
🌷 <사용법 정리>
Store
Store는 상태가 관리되는 오직 하나뿐인 저장소의 역할을 합니다. Redux 앱의 state가 저장되어 있는 공간이죠. 아래 코드와 같이 createStore 메서드를 활용해 Reducer를 연결해서 Store를 생성할 수 있습니다.
import { createStore } from 'redux';
const store = createStore(rootReducer);
Reducer
Reducer는 Dispatch에게서 전달받은 Action 객체의 type 값에 따라서 상태를 변경시키는 함수입니다.
const count = 1
// Reducer를 생성할 때에는 초기 상태를 인자로 요구합니다.
const counterReducer = (state = count, action) => {
// Action 객체의 type 값에 따라 분기하는 switch 조건문입니다.
switch (action.type) {
//action === 'INCREASE'일 경우
case 'INCREASE':
return state + 1
// action === 'DECREASE'일 경우
case 'DECREASE':
return state - 1
// action === 'SET_NUMBER'일 경우
case 'SET_NUMBER':
return action.payload
// 해당 되는 경우가 없을 땐 기존 상태를 그대로 리턴
default:
return state;
}
}
// Reducer가 리턴하는 값이 새로운 상태가 됩니다.
이때, Reducer는 순수함수여야 합니다. 외부 요인으로 인해 기대한 값이 아닌 엉뚱한 값으로 상태가 변경되는 일이 없어야 하기 때문입니다.
만약 여러 개의 Reducer를 사용하는 경우, Redux의 combineReducers 메서드를 사용해서 하나의 Reducer로 합쳐줄 수 있습니다.
import { combineReducers } from 'redux';
const rootReducer = combineReducers({
counterReducer,
anyReducer,
...
});
Action
Action은 말 그대로 어떤 액션을 취할 것인지 정의해 놓은 객체로, 다음과 같은 형식으로 구성됩니다.
// payload가 필요 없는 경우
{ type: 'INCREASE' }
// payload가 필요한 경우
{ type: 'SET_NUMBER', payload: 5 }
여기서 type 은 필수로 지정을 해 주어야 합니다. 해당 Action 객체가 어떤 동작을 하는지 명시해 주는 역할을 하기 때문이며, 대문자와 Snake Case로 작성합니다. 여기에 필요에 따라 payload를 작성해 구체적인 값을 전달합니다.
보통 Action을 직접 작성하기보다는 Action 객체를 생성하는 함수를 만들어 사용하는 경우가 많습니다. 이러한 함수를 액션 생성자(Action Creator)라고도 합니다.
// payload가 필요 없는 경우
const increase = () => {
return {
type: 'INCREASE'
}
}
// payload가 필요한 경우
const setNumber = (num) => {
return {
type: 'SET_NUMBER',
payload: num
}
}
Dispatch
Dispatch는 Reducer로 Action을 전달해 주는 함수입니다. Dispatch의 전달인자로 Action 객체가 전달됩니다.
// Action 객체를 직접 작성하는 경우
dispatch( { type: 'INCREASE' } );
dispatch( { type: 'SET_NUMBER', payload: 5 } );
// 액션 생성자(Action Creator)를 사용하는 경우
dispatch( increase() );
dispatch( setNumber(5) );
Action 객체를 전달받은 Dispatch 함수는 Reducer를 호출합니다.
여기까지 Store, Reducer, Action, Dispatch 개념들을 코드로 구성하는 것은 완료했습니다. 그렇다면 이제 이 개념들을 연결시켜주어야 할 텐데요. Redux Hooks를 이용하면 됩니다.
Redux Hooks는 React-Redux에서 Redux를 사용할 때 활용할 수 있는 Hooks 메서드를 제공합니다. 그중에서 크게 useSelector(), useDispatch() 이 두 가지의 메서드를 기억하면 됩니다.
useDispatch()
useDispatch()는 Action 객체를 Reducer로 전달해 주는 Dispatch 함수를 반환하는 메서드입니다. 위에서 Dispatch를 설명할 때 사용한 dispatch 함수도 useDispatch()를 사용해서 만든 것입니다.
import { useDispatch } from 'react-redux'
const dispatch = useDispatch()
dispatch( increase() )
console.log(counter) // 2
dispatch( setNumber(5) )
console.log(counter) // 5
useSelector()
useSelector()는 컴포넌트와 state를 연결하여 Redux의 state에 접근할 수 있게 해주는 메서드입니다.
// Redux Hooks 메서드는 'redux'가 아니라 'react-redux'에서 불러옵니다.
import { useSelector } from 'react-redux'
const counter = useSelector(state => state)
console.log(counter) // 1