redux-thunk란?

  • Firestore에서 데이터를 가져올 때 비동기 통신을 함
  • 리덕스에서 비동기 통신을 할 때 미들웨어가 필요함
  • 일반 액션 생성 함수는 객체를 반환하는데 redux-thunk는 객체 대신 함수를 생성하는 액션 생성함수를 작성할 수 있게 해줌
  • 함수를 생성하면 특정 액션이 발생하기 전에 조건을 주거나 행동을 할 수 있음

미들웨어

  • 리덕스 데이터를 수정할 때 액션 디스패치 → 리듀서에서 처리
  • 미들웨어가 있으면 액션 디스패치 → 미들웨어가 할일 → 리듀서에서 처리

설치하기

yarn add redux-thunk

configStore.js

  • redux-thunk 적용 전 configStore.js
import {createStore, combineReducers} from 'redux';
import bucket from './modules/bucket';
import {createBrowserHistory} from 'history';

export const history = createBrowserHistory();
const rootReducer = combineReducers({bucket});
const store = createStore(rootReducer);

export default store;
  • redux-thunk 적용 후 ⬇
import {createStore, combineReducers, applyMiddleware, compose} from 'redux';
import thunk from 'redux-thunk';
import bucket from './modules/bucket';
import {createBrowserHistory} from 'history';

export const history = createBrowserHistory();

const middlewares = [thunk];

const enhancer = applyMiddleware(...middlewares);
const rootReducer = combineReducers({bucket});
const store = createStore(rootReducer, enhancer);

export default store;

 

Load하기

bucket.js 수정

  • Firebase랑 통신하는 함수 생성
const bucket_db = firestore.collection('bucket');

export const loadBucketFB = () => {
	return function (dispatch) {
		bucket_db.get().then((docs) => {
			let bucket_data = [];
			docs.forEach((doc) => {
				if(doc.exists){
					bucket_data = [...bucket_data, {id: doc.id, ...doc.data()}];
				}
			});

			dispatch(loadBucket(bucket_data));
		});
	};
};
  • 리듀서 수정
case 'bucket/LOAD': {
	if (action.bucket.length > 0) {
		return {list: action.bucket};
	}

	return state;
}

App.js 수정

const mapDispatchToProps = (dispatch) => ({
	load: () => {
		dispatch(loadBucketFB());
	},
	create: (new_item) => {
		dispatch(createBucket(new_item));
	}
});

 

Create 하기

bucket.js 수정

  • Firebase와 통신하는 함수 생성
export const addBucketFB = (bucket) => {
	return function (dispatch) {
		let bucket_data = {text: bucket, completed: false};
		bucket_db
			.add(bucket_data)
			.then((docRef) => {
				bucket_data = {...bucket_data, id: docRef.id};
				dispatch(createBucket(bucket_data));
			});
			.catch((err) => {
				window.alert('오류 발생');
			});
	};
};
  • 리듀서 수정
case 'bucket/CREATE': {
	const new_bucket_list = [
		...state.list,
		action.bucket,
	];
	return {list: new_bucket_list};
}

App.js

const mapDispatchToProps = (dispatch) => ({
	load: () => {
		dispatch(loadBucketFB());
	},
	create: (new_item) => {
		dispatch(addBucketFB(new_item));
	}
});

 

Update 하기

bucket.js

export const updateBucketFB = (bucket) => {
	return function (dispatch, getState) {
		const _bucket_data = getState().bucket.list[bucket];
		if (!_bucket_data.id) {
			return;
		}

		let bucket_data = {..._bucket_data, completed: true};
		bucket_db
			.doc(bucket_data.id)
			.update(bucket_data)
			.then((res) => {
				dispatch(updateBucket(bucket));
			})
			.catch((err) => {
			});
	};
};

Detail.js

<button onClick={() => {
		dispatch(updateBucketFB(bucket_index));
		props.history.goBack();
	}}>완료하기</button>

 

Delete 하기

bucket.js

export const deleteBucketFB = (bucket) => {
	return function (dispatch, getState) {
		const _bucket_data = getState().bucket.list[bucket];
		if (!_bucket_data.id) {
			return;
		}
		bucket_db
			.doc(_bucket_data.id)
			.delete()
			.then((res) => {
				dispatch(deleteBucket(bucket));
			})
			.catch((err) => {
			});
	};
};

Detail.js

<button onClick={() => {
		dispatch(deleteBucketFB(bucket_index));
		props.history.goBack();
	}}>삭제하기</button>

+ Recent posts