반응형
Redux란
JavaScript 애플리케이션(특히 React)에서 전역 상태 관리를 할 수 있게 해주는 라이브러리
Redux를 사용하면 전역 상태를 '스토어'라는 중앙 데이터 저장소에 관리하며, 컴포넌트 간 상태 공유 및 상태 업데이트가 간편해진다
설치
npm install redux react-redux
구성 요소를 다 만들었다면 React-Redux에서 제공하는 기능을 사용
- App과 전역 상태 저장소 연결 - <Provider store={store}>
- 상태 저장소에서 상태 꺼내서 사용 - useSelector()
- dispatch함수 만들어서 사용 - useDispatch()
Redux의 데이터 흐름 (flux패턴)
Redux는 Flux패턴을 기반으로 동작
이 패턴은 단방향 데이터 흐름을 가정하여, 데이터의 변경이 한 방향으로만 흐르도록 하여 상태를 예측 가능하게 만듬
- View(컴포넌트)에서 Action을 호출하여 원하는 상태 변경을 요청
- Action이 Reducer로 전달되어 상태 변경 로직을 실행하고 새로운 상태를 반환
- Store는 새로운 상태를 저장하며, View는 이를 반영하여 UI를 업데이트함
단방향 흐름 덕분에 상태가 변화하는 과정이 명확해지고, 코드 디버깅이 쉬워짐
Action, Dispatch, Reducer, Store의 역할
Action
- 애플리케이션에서 발생한 일을 설명하는 객체
- 주로 type 속성과 필요한 데이터(payload)로 구성
// actions.js
// 액션 타입 정의
const INCREMENT = 'INCREMENT';
const DECREMENT = 'DECREMENT';
// 액션 생성 함수 정의
export const increment = () => {
return {
type: INCREMENT, // 증가 액션
};
};
export const decrement = () => {
return {
type: DECREMENT, // 감소 액션
};
};
Dispatch
- Action을 Reducer(Store)에 전달하는 함수
- dispatch(action)을 호출하면 Store에서 Reducer가 실행되고, 새로운 상태가 반환 됨
- useDispatch를 사용하여 Dispatch를 호출할 수 있음
// Counter.js
import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { increment, decrement } from './actions';
const Counter = () => {
// Redux의 상태 값 가져오기
const count = useSelector((state) => state.count);
// 액션을 디스패치하기 위한 디스패치 함수 가져오기
const dispatch = useDispatch();
return (
<div>
<h1>Counter: {count}</h1>
<button onClick={() => dispatch(increment())}>+</button> {/* 증가 */}
<button onClick={() => dispatch(decrement())}>-</button> {/* 감소 */}
</div>
);
};
export default Counter;
Reducer
- Action을 받아 상태를 변경하는 함수
- Reducer는 현재 상태와 액션을 입력으로 받아서 새로운 상태를 반환함
- Reducer는 순수 함수여야 하며, 상태를 직접 수정하지 않고 새로운 상태 객체를 반환함
// reducer.js
// 초기 상태 정의
const initialState = { count: 0 };
// 리듀서 함수 정의
export const counterReducer = (state = initialState, action) => {
switch (action.type) {
case 'INCREMENT':
return { ...state, count: state.count + 1 }; // 상태 변경
case 'DECREMENT':
return { ...state, count: state.count - 1 }; // 상태 변경
default:
return state; // 기본 상태 반환
}
};
Store
- Store는 Redux의 중앙 저장소로, 애플리케이션의 모든 상태를 관리
- 애플리케이션은 createStore()함수를 통해 하나의 Store만을 가짐
- Store는 dispatch()와 getState()메서드를 통해 상태를 업데이트하고 읽을 수 있음
// store.js
import { legacy_createStore as createStore } from 'redux';
import { counterReducer } from './reducer';
// 스토어 생성
const store = createStore(counterReducer);
export default store;
useDispatch()와 useSelector()의 역할
useDispatch()
- Redux 스토어의 dispatch 함수를 반환하는 훅, React 컴포넌트에서 액션을 스토어로 전달할 수 있게 함
- dispatch() 를 사용하여 상태 업데이트를 트리거 함
- Ex) const dispatch = useDispatch(); dispatch(addTodoAction);
useSelector()
- Redux 스토어에서 특정 상태를 선택하여 React 컴포넌트에서 사용할 수 있게 하는 훅
- Ex) const todos = useSelector((state) => state.todos );
- useSelector는 필요한 상태만 구독하므로 불필요한 상태 변화를 방지해 성능 최적화에 도움이 됨
Redux-Thunk란
Redux에서 비동기 작업을 처리할 수 있게 도와주는 미들웨어
Redux는 기본적으로 동기작업만을 다루지만, redux-thunk
를 사용하면 액션 크리에이터가 함수를 반환할 수 있게 되어 비동기 작업을 쉽게 처리할 수 있음
예를 들어, API 호출 후에 상태를 업데이트해야할 경우, redux-thunk
를 통해 비동기 액션을 작성할 수 있음
dispatch()함수를 인수로 받아서 비동기 요청이 끝난 후 적절한 액션을 디스패치 함
// 예: 비동기 액션 생성자
const fetchData = () => {
return async (dispatch) => {
dispatch({ type: 'FETCH_START' });
try {
const response = await fetch('/api/data');
const data = await response.json();
dispatch({ type: 'FETCH_SUCCESS', payload: data });
} catch (error) {
dispatch({ type: 'FETCH_FAILURE', payload: error });
}
};
};
redux-thunk는 이러한 비동기 로직을 액션과 분리하여 데이터 처리를 관리하기 쉽게 만들어 줌
반응형
'FE > React & Redux' 카테고리의 다른 글
React | State와 Props 데이터 관리 (0) | 2024.10.29 |
---|---|
React | Redux Toolkit 전역 상태 관리 (0) | 2024.10.28 |
React | Context API (3) | 2024.10.25 |
React | 전역상태 관리 (3) | 2024.10.25 |
React | Tailwind CSS (2) | 2024.10.24 |