일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- version management
- js pattern
- peerdependencies
- middleware pattern
- 이벤트
- package management
- 자바스크립트 패턴
- 딥다이브
- 자바스크립트 딥다이브
- 자바스크립트
- 제너레이터와 async/await
- DOM
- 프로그래머스
- const
- Babel과 Webpack
- 모던 자바스크립트 Deep Dive
- 올림픽 통계 서비스 최적화
- 브라우저의 렌더링 과정
- mixin pattern
- 프론트엔드 성능 최적화 가이드
- 블로그 서비스 최적화
- 스코프
- 학습내용정리
- 새 코드 받아오기
- 진행기록
- pr review
- js pattern
- unique identifiers
- 이미지 갤러리 최적화
- 커리어
- Today
- Total
Dev Blog
10. Redux 본문
Achievement goals
- 상태 관리 라이브러리가 왜 필요한지 이해할 수 있다.
- Redux (혹은 Flux Pattern)에서 사용하는 Action, Reducer 그리고 Store의 의미와 특징을 이해할 수 있다.
- Redux의 3가지 원칙이 무엇이며, 주요 개념과 어떻게 연결되는지 이해할 수 있다.
- Presentational 컴포넌트와 Container 컴포넌트의 개념을 이해할 수 있다.
- Redux hooks(useSelector, useDispatch)를 사용해 store 를 업데이트할 수 있다.
Redux 란?
상태 관리 라이브러리
목적?
React 특성인 불필요한 렌더링을 보완하기 위함.
React 렌더링 조건이라 하면,
1. State 가 변경된 경우
2. State 변경으로 인해 Props 가 변경된 경우
3. 부모 컴포넌트가 렌더링된 경우
즉, state 값 변경으로 인해 re-rendering 이 발생하는데
이 때 re-rendering 이 필요없는 컴포넌트(state 값에 영향을 받지 않는) 또한 렌더링되는 성능저하를 초래한다.
프로젝트의 규모가 커질수록 data flow 가 복잡해질 수 있고 버그나 오류로 인해 트래킹이 불가할 수 있다.
예) React this.state 사용 & React Hooks 사용
아래와 같은 경우, 어떤 상태가 변하는지에 상관없이 일괄적으로 전체가 re-rendering 되는 것을 확인할 수 있다.
currentVideo 가 변경되었는데, <VideoList/> 도 불필요한 렌더링이 발생하여 프로그램의 성능이 저하될 수 있다.
어떻게?
컴포넌트와 상태를 분리 Store 라는 오직 하나의 상태관리 공간을 만들어 상태 변화가 생겼을 때 해당 상태를 사용하는 컴포넌트만 렌더링 시킨다.
before)
after)
Redux 의 세 가지 원칙
1. Single source of truth : store 에 저장. 상태 관리를 위한 단 하나의 공간.
2. State is read-only: action 으로 state 를 변경한다. redux 가 reducer 를 통해 상태를 변경하고, react 컴포넌트는 해당 데이터를 읽기 전용으로 불러온다.
3. Changes are made with pure functions: reducer 와 관련. pure function => side effect 가 없다는 것.
store
상태가 관리되는 오직 하나의 공간
action
자바스크립트 객체. App 에서 얻는 이 정보(action 객체)를 store 에 운반한다.
type 을 반드시 작성해줘야 하는데, 이 type 에 따라 reducer 가 동작하기 때문이다.
reducer
현재 상태와 action 을 이용하여 다음 상태를 만든다.
여기에서 Dispatch 는 메소드. 이 메소드가 reducer 를 호출한다.
reducer 는 action 객체의 type 에 따라 동작을 선택하고, payload(변경된 데이터)를 활용하여 Store 를 업데이트 한다.
Overview
Redux 의 장점
1. 상태를 예측 가능하게 만들어준다.
2. 유지보수가 용이하다.
3. 디버깅에 유리하다. action과 state log를 기록하면 추적이 가능. => redux dev tool 로 확인할 수 있다.
4. 테스트를 붙이기 쉽다.
순수함수를 사용하기 때문에 테스트를 붙이기 쉽다.
5. React 는 UI 만 담당하는 것과 같아지기 때문에 Redux를 통한 데이터 관리가 쉬워진다.
모든 데이터는 Redux 로 관리.
Presentational Component VS Container Component
1) Presentational Component
: Props 에서 data 를 읽고 props 에서 콜백을 호출하는 Redux 와 연관 없는 컴포넌트
2) Container Component
: Redux 의 State 에 접근하여 데이터(Store)에 영향을 줄 수 있는 컴포넌트로 Redux 와 연관이 있다.
How to approach and update Store
Redux hooks 인 useSelector, useDispatch 를 이용
Redux Thunk middleware , 비동기 액션 생산자
allows you to write action creators that return a function instead of an action. The thunk can be used
to delay the dispatch of an action, or to dispatch only if a certain condition is met.
The inner function receives the store methods dispatch and getState as parameters.
리덕스에서 비동기 작업을 처리할 때는 redux-thunk라는 미들웨어를 많이 사용합니다.
비동기 액션 생산자는, 상태에 따라 동기 액션 생산자를 호출해줍니다. 여기서 말하는 상태는 비동기 요청 시작/완료/실패 등을 포함할 수 있습니다. 비동기 액션 생산자는 리듀서로 연결되지 않고, 직접 dispatcher를 통해 스토어로 새로운 상태를 보내줍니다.
함수를 dispatch 할 때에는, 해당 함수에서 dispatch 와 getState 를 파라미터로 받아와주어야 합니다.
이 함수를 만들어주는 함수를 우리는 thunk 라고 부릅니다.
thunk?
A thunk is a function that wraps an expression to delay its evaluation.
// calculation of 1 + 2 is immediate
// x === 3
let x = 1 + 2;
// calculation of 1 + 2 is delayed
// foo can be called later to perform the calculation
// foo is a thunk!
let foo = () => 1 + 2;
1) An action creator that returns a function to perform asynchronous dispatch:
비동기적인 dispatch 를 실행하기 위한 함수를 리턴하는 액션 creator
const INCREMENT_COUNTER = 'INCREMENT_COUNTER';
function increment() {
return {
type: INCREMENT_COUNTER,
};
}
function incrementAsync() {
return (dispatch) => {
setTimeout(() => {
// Yay! Can invoke sync or async actions with `dispatch`
dispatch(increment());
}, 1000);
};
}
이 경우, 동기적으로 dispatch 를 통해 increment() 의 리턴값을 리듀서에 전달하고 1초 뒤(1000) dispatch 를 통해 increment() 의 리턴값을 리듀서에 재 전달한다.
2) An action creator that returns a function to perform conditional dispatch:
조건적인 dispatch 를 실행하기 위한 함수를 리턴하는 액션 creator
function incrementIfOdd() {
return (dispatch, getState) => {
const { counter } = getState();
if (counter % 2 === 0) {
return;
}
dispatch(increment());
};
}
이 경우, counter 가 짝수인 경우 dispatch 를 통해 increment() 의 리턴값이 리듀서에 전달된다.
Check in Code
const { createStore } = require("redux");
//!초기 state(데이터)를 정의한다.
const initState = {
name: "김코딩",
posts: [],
};
//!action creator
//!action 은 객체로 data 를 받으면 type 과 payload(여기에서 data) 가 reducer 에게 전달된다.
const changeUsername = (data) => {
return {
type: "CHANGE_NAME",
data,
};
};
const addPost = (post) => {
return {
type: "ADD_POST",
post,
};
};
//! reducer: 실제 메소드로 데이터를 변경해준다.
//! initState(prevState)와 action 을 받아 type 에 따라
//! payload를 활용하여 특정 method 를 실행시킨다.
const reducer = (prevState, action) => {
switch (action.type) {
case "CHANGE_NAME":
return {
...prevState,
name: action.data,
};
case "ADD_POST":
return {
...prevState,
posts: [...prevState.posts, action.post],
};
default:
return prevState;
}
};
//! Store
//! createStore 메소드를 활용. createStore(reducer, [preloadedState], [enhancer])
//! reducer: returns the next state tree, given the current state tree and an action to handle.
//! [preloadedState]: initState
//! [enhandcer]: to enhance the store with third-party capabilities such as middleware, time travel, persistence, etc.
const store = createStore(reducer, initState);
//! dispatch
//! The base dispatch function always synchronously sends an action to the store's reducer,
//! along with the previous state returned by the store, to calculate a new state.
//! It expects actions to be plain objects ready to be consumed by the reducer.
store.dispatch(changeUsername("김제이"));
store.dispatch(addPost("포스트1"));
store.dispatch(addPost("포스트2"));
console.log(store.getState());
결과값은 다음과 같다.
'BootCamp_Codestates > IM Tech Blog' 카테고리의 다른 글
13. authentication (0) | 2021.01.20 |
---|---|
11. Databases (0) | 2021.01.13 |
8-1. React 데이터흐름 & State 끌어올리기 (0) | 2021.01.05 |
8. React Part1 (0) | 2021.01.01 |
5. Asynchronous & Promise (0) | 2020.12.21 |