티스토리 뷰
리덕스란?
- 자바스크립트 상태 관리 라이브러리
리덕스가 왜 필요할까?
- 프로젝트 규모가 커질 수록 컴포넌트 개수도 많아질 것이고 그에 따라 서로 다른 컴포넌트끼리 공유하는 상태(state) 또한 많아진다.
- 리액트는 부모 컴포넌트에서 자식 컴포넌트로 데이터가 흐르는 단방향 패턴이며 자식 컴포넌트들 간 다이렉트로 데이터 전달이 불가능하다.
리액트만으로 상태를 관리할 때 문제점
Props drilling 이슈
- 하위 컴포넌트에서 상위 컴포넌트에 있는 상태를 변화시키기 위해서는 여러 번의 props 전달을 통해야 한다.
- 전달만을 위한 props가 생기기 때문에 코드가 복잡해지고 유지보수가 어려워지며, 불필요한 리렌더링이 많아지는 단점이 있다.
리덕스를 이용할 때 이점
- 리덕스를 이용하면 Store라는 전역 상태 저장소에서 상태를 꺼내쓸 수 있기 때문에 불필요한 컴포넌트간 전달이 사라지고 필요한 컴포넌트만 리렌더링 할 수 있다.
리덕스의 구조
Store
- 상태가 관리되는 단 하나의 저장소로 필요한 상태들과 리듀서가 저장되어 있다.
Redux
import React from 'react'
import { render } from 'react-dom'
import App from './components/App'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import counterReducer from './reducers'
const store = createStore(counterReducer)
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
- store를 생성해서 reducer를 연결하는 작업
- Provider로 App 컴포넌트를 감싼 것은, App컴포넌트에게 store 접근 권한을 준 것이라고 할 수 있다.
Redux-toolkit
import { configureStore } from '@reduxjs/toolkit'
export default configureStore({
reducer: {
counter: counterReducer
}
})
- 현재 createStore는 deprecated 되어 있으며 공식문서에서는 redux-toolkit의 configureStore의 사용을 권장하고 있다!
Reducer
- Dispatch에게서 현재의 state와 action을 인자로 받아서 store에 접근하여 전달받은 Action 객체의 상태를 변경시키는 함수이다.
- Reducer는 사이드이펙트가 발생하면 안 되므로 순수함수여야 한다!
Redux
const count = 1
const counterReducer = (state = count, action) => {
switch (action.type) {
case 'INCREASE':
return state + 1
case 'DECREASE':
return state - 1
default:
return state;
}
}
Redux-toolkit
import { createSlice } from '@reduxjs/toolkit'
export const counterSlice = createSlice({
name: 'counter',
initialState: {
value: 0
},
reducers: {
increment: state => {
state.value += 1
},
decrement: state => {
state.value -= 1
},
incrementByAmount: (state, action) => {
state.value += action.payload
}
}
})
export const { increment, decrement, incrementByAmount } = counterSlice.actions
export default counterSlice.reducer
Action
- 상태를 변화시키려는 의도를 표현한 객체로 action type와 전송할 데이터(payload)로 이루어져 있다.
// payload가 필요 없는 경우
{ type: 'INCREASE' }
// payload가 필요한 경우
{ type: 'SET_NUMBER', payload: 5 }
Action creator
- Action이 동작을 표현한 객체라면 Action creator는 Action을 생성해 실제 객체로 만들어주는 함수이다.
export const increase = () => {
return {
type: 'INCREASE',
};
};
export const decrease = () => {
return {
type: 'DECREASE',
};
};
// payload가 필요한 경우
export const setNumber = (num) => {
return {
type: 'SET_NUMBER',
payload: num
}
}
Dispatch
- Reducer로 Action을 전달해주는 함수이다. 따라서 Dispatch의 전달인자로 Action 객체가 들어가게 된다.
Redux hooks
useDispatch()
- Action 객체를 Reducer로 전달해주는 Dispatch 함수를 반환하는 메소드
import { useDispatch } from 'react-redux'
const dispatch = useDispatch();
dispatch(increase());
useSelector()
- 컴포넌트와 state를 연결해서 Redux의 state에 접근할 수 있게 해주는 메소드
import { useSelector } from 'react-redux'
const counter = useSelector(state => state);
Redux
import React from 'react';
import './style.css';
import { useDispatch } from 'react-redux';
import { increase, decrease } from './index.js';
export default function App() {
const dispatch = useDispatch();
const state = useSelector((state) => state);
const plusNum = () => {
dispatch(increase());
};
const minusNum = () => {
dispatch(decrease());
};
return (
<div className="container">
<h1>{`Count: \${state}`}</h1>
<div>
<button className="plusBtn" onClick={plusNum}>
+
</button>
<button className="minusBtn" onClick={minusNum}>
-
</button>
</div>
</div>
);
}
Redux-toolkit
import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { decrement, increment } from './counterSlice'
import styles from './Counter.module.css'
export function Counter() {
const count = useSelector(state => state.counter.value)
const dispatch = useDispatch()
return (
<div>
<div>
<button
aria-label="Increment value"
onClick={() => dispatch(increment())}
>
Increment
</button>
<span>{count}</span>
<button
aria-label="Decrement value"
onClick={() => dispatch(decrement())}
>
Decrement
</button>
</div>
</div>
)
}
리덕스의 흐름
- UI에서 컴포넌트 내에 존재하는 이벤트가 호출
- 이벤트와 연결된 액션 생성자가 호출
- 액션 생성자에서 생성된 액션이 호출
- 디스패치가 액션을 리듀서로 전달
- 리듀서에서 디스패치된 액션에 따라 상태값을 변경
- 변경사항이 렌더링
참고 자료
반응형
'개발냥이 > 자바스크립트(Javascript)' 카테고리의 다른 글
[자바스크립트] 비동기 통신_async/await (0) | 2023.05.02 |
---|---|
[자바스크립트] 비동기 통신_프로미스(Promise) (0) | 2023.04.25 |
[자바스크립트] 동기와 비동기(feat. 콜백 함수) (0) | 2023.04.18 |
[JavaScript] 프로토타입(Prototype) (0) | 2023.03.15 |
[JavaScript] 클래스 문법 (0) | 2023.03.15 |
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- Nest
- DP
- 정렬
- 형변환
- BFS
- 프로그래머스
- CS
- Queue
- 이분탐색
- 자바
- Spring
- 자바bfs
- 자바트리
- Comparator
- 타입스크립트
- 스프링부트
- SQLD
- 자바dp
- 스프링
- java
- 해시맵
- JPA
- 리액트
- 알고리즘
- Algorithm
- dfs
- SQL
- 자바스크립트
- JavaScript
- 백준
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함