react redux와 Redux-saga에 대해 알아보고 간단히 사용해보자
Redux란 ?
가장 많이 쓰이는 상태관리 라이브러리.
컴포넌트 끼리 상태(데이터, 로직)를 공유하게 될 때 여러 컴포넌트를 거치지 않고 바로 상태 값을 전달하거나 받아볼 수 있게 해준다.우체국 같은 느낌?
글로벌 상태 관리를 하게 될 때 굉장히 효과적 !
props 가 필요한 곳으로 전달되게 하기 위해 해당 props 를 사용하지 않는 컴포넌트를 거쳐가야 해서 불필요한 리렌더링이 발생하고, 이를 전달하는 것은 굉장히 귀찮은 작업이 된다.
객체의 형태로 표현되며 상태변화/조회 등이 필요할 때 발생시킨다.
액션을 설명하는 type 필드를 필수적으로 가지고 있어야하고 그 외의 값들은 마음대로 넣을 수 있다.
{
type: "ADD_COUNT",
}
{
type: "TOGGLE_TODO",
id: 0
}
{
type: "ADD_TODO",
data:{
id: 0,
content: "",
done: false
}
}
// 액션 타입 정의
const ADD_TODO = 'ADD_TODO';
const TOGGLE_TODO = 'TOGGLE_TODO';
const ADD_COUNT = 'ADD_COUNT';
액션을 만드는 함수로 파라미터를 받아와서 액션 객체 형태로 만들어주는 역할을 한다.
function toggleTodo = id => ({
return {
type: "TOGGLE_TODO",
id
});
state와 action을 파라미터로 받아와서 변화를 일으키는 함수
// 초깃값 설정
const initialState = [],
// reducer 함수 정의
function reducer(state = initialState, action) {
switch (action.type) {
case ADD_TODO:
return state.concat(action.data);
case TOGGLE_TODO:
return state.map(data => data.id === action.id ? {
...todo, done:todo.done!
});
...
default:
// 지원하지 않는 액션은 상태 유지
return state;
}
}
상태와 리듀서, 내장함수들이 저장되어 있는 곳.
한 애플리케이션 당 하나의 스토어 사용
import { createStore } from 'redux';
const store = createStore(reducer);
스토어의 내장함수 중 하나로 액션을 발생 시키는 것을 말한다.
dispatch(toggleSwitch())
스토어의 내장함수 중 하나로 함수 형태의 값을 파라미터로 받아 액션이 디스패치 되었을 때 전달해준 함수가 호출된다.
react와 함께쓰면 이미 기능이 내장되어 있어 사용할 일은 없을 가능성이 많다.
const listener = () => console.log('업데이트 됐어요!')
const unsubscribe = store.subscribe(listener);
// subscribe 함수는 구독 기능을 끄는 unsubscribe 반환
$ yarn add redux
$ yarn add react-redux
📃 src/modules/member.js
// 액션 타입 설정
const SET_MEMBERS = 'member/SET_MEMBERS';
// 액션 생성 함수 - export
export const setMembersToStore = members => ({
type: SET_MEMBERS,
members,
});
// 초깃값 설정
const initialState = {
members: [],
};
// reducer 함수 정의 - export default
export default function reducer(state = initialState, action) {
switch (action.type) {
case SET_MEMBERS:
console.log('a :', action);
return {
...state,
members: action.members,
};
default:
// 지원하지 않는 액션은 상태 유지
return state;
}
}
📃 MemberList.js
...
// redux 사용
import { setMembersToStore } from '../../modules/member';
import { useDispatch } from 'react-redux';
// action dispatch 정의
const dispatch = useDispatch();
const saveMembersToStore = data => dispatch(setMembersToStore(data));
// dispatch 호출
useEffect(() => {
(async () => {
const { data } = await getMembers();
...
// store에 저장
saveMembersToStore(data);
})();
}, []);
📃 modules/index.js
import { combineReducers } from 'redux';
import member from './member';
const rootReducer = combineReducers({
member,
});
export default rootReducer;
📃 index.js
...
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import rootReducer from './modules';
// store 생성
const store = createStore(rootReducer);
console.log(store.getState());
//{member: { members: [] }
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById('root'),
);
📃 Main.js
// 스토에어서 불러오기
import { useSelector } from 'react-redux';
function Main() {
// 스토어
const { members } = useSelector(state => state.member);
console.log('saved members : ', members);
...
}
// [] -> [{}, {} ...]
🧚 결과
Object
member:
members: Array(0)
[SUCCESS] GET MEMBERS ---->
Object
data: (13) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…
Redux-saga ?
리덕스의 미들웨어로 비동기 작업, 로깅 등의 확장적인 작업들을 할 수 있게 해준다.
액션을 모니터링하고 있다가, 특정 액션이 발생하면 이에 따라 특정 작업을 하는 방식으로 사용한다.
특정 액션이 발생했을 때 상태 값이나 응답 상태 등에 따라 다른 액션을 디스패치 하거나 추가적인 로직을 적용 해야될 때 사용할 수 있다.
특정시간 후 함수를 실행할 수 있게 해준다.
import { delay } from 'redux-saga/effects';
function* toggleTodoSaga() { // 제너레이터 함수 형태
yield delay(1000);
}
특정 액션을 디스패치 해준다.
import { put } from 'redux-saga/effects';
function* toggleTodoSaga() {
...
yield put(toggleTodo()); // put은 특정 액션을 디스패치 해줍니다.
}
다특정 함수를 호출하고, 결과물이 반환 될 때까지 기다릴 수 있어 동기적 실행이 가능하다.
import { call } from 'redux-saga/effects';
import * as todosAPI from '../api/todos'
function* toggleTodoSaga() {
const todo = yield call(postsAPI.getTodoById, param);
...
}