์๋๋ฆฌ์ค: ํ๋ก์ ํธ์ ๋ชจ๋ธ A์ ๋ชจ๋ธ B์ ํด๋นํ๋ ๋ ๊ฐ์ ํ์ด์ง A์ B๊ฐ ์๋ ๊ฒฝ์ฐ ๊ฐ ํ์ด์ง์ ์ผ๋ถ ๋น๋๊ธฐ ๋คํธ์ํฌ ์์ฒญ์ด ์์ผ๋ฉฐ ์ด๋ ํจ๊ณผ์์ ์์๋๊ณ ๋ฐํ๋ ๋ฐ์ดํฐ๋ ๊ฐ์๊ธฐ๋ฅผ ํตํด ํ์ฌ ๋ชจ๋ธ์ ๊ธฐ๋ก๋ฉ๋๋ค. ์ํ.
Aํ์ด์ง๋ Bํ์ด์ง๋ฅผ ๋ ๋ ๋ ๋ค์์ ์ฌ์ฌ์ฉํ ๋ ๋ํฐ ๋ฐ์ดํฐ๊ฐ ๋์ง ์๋๋ก ํด๋น ๋ชจ๋ธ์ ๋ฐ์ดํฐ๋ฅผ ์ง์ฐ๊ณ ์ถ์ต๋๋ค.
componentWillUnmount ๋ฉ์๋์์ ๋ชจ๋ธ์ ๋ช
ํํ ๊ฐ์๊ธฐ๋ฅผ ์์ฑํ์ต๋๋ค.
๋์คํจ์น({ type:${model.namespace}/clear})
์ฌ์ฉ์๋ Aํ์ด์ง์์ Bํ์ด์ง๋ก ์ง์ ํ๊ณ A๋ชจ๋ธ์ ๋ฐ์ดํฐ๋ ์ ๋ฆฌ๋์ด ์ด๊ธฐ์ํ๋ก ๋ณต์๋๋ค.
์ฌ์ฉ์๊ฐ ํ์ด์ง A์์ ํ์ด์ง B์ ๋ค์ด๊ฐ ๋ ํ์ด์ง A์์ ๋น๋๊ธฐ์ ๋คํธ์ํฌ ์์ฒญ์ด ๋ฐ์ํ๊ณ ๋คํธ์ํฌ ์์ฒญ์ด ์๋ฃ๋๊ธฐ ์ ์ ํ์ด์ง B์ ๋ค์ด๊ฐ๋ฉด ํ์ด์ง A๋ ๋จผ์ ํด๋ฆฌ์ด ๋ฆฌ๋์๋ฅผ ํตํด ๋ชจ๋ธ A ๋ฐ์ดํฐ๋ฅผ ์ง์๋๋ค. ์์ฒญ์ด ์๋ฃ๋๋ฉด ๋ฐํ๋ ๋ฐ์ดํฐ๊ฐ ๋ชจ๋ธ A์ ๋ค์ ์์ฑ๋์ด ๋ชจ๋ธ A์ ์ด์ ๋น์ฆ๋์ค์์ ๋ํฐ ๋ฐ์ดํฐ๊ฐ ์์ฑ๋ฉ๋๋ค.
A ํ์ด์ง๋ฅผ ๋๊ฐ ๋ ์ง์ ๋ ํจ๊ณผ๋ฅผ ์ทจ์ํ๊ฑฐ๋ ๋ค์์คํ์ด์ค์ ๋ชจ๋ ํจ๊ณผ๋ฅผ ์ทจ์ํ ์ ์์ต๋๊น? (redux-saga์์ ์ทจ์์ ์ ์ฌ)
v2.2.3
๋ชจ๋ธ ๊ตฌ๋ ์์ ๋ผ์ฐํ ๋ณ๊ฒฝ ์ฌํญ์ ๋ชจ๋ํฐ๋งํ๊ณ ํ์ด์ง๊ฐ A ํ์ด์ง๊ฐ ์๋ ๊ฒฝ์ฐ(A ํ์ด์ง ๋๊ฐ๊ธฐ) ๋๋ A ํ์ด์ง(A ํ์ด์ง ์ ๋ ฅ)์ธ ๊ฒฝ์ฐ ๋ชจ๋ธ A์ ์ํ๋ฅผ ์๋์ผ๋ก ์ง์ธ ์ ์์ต๋๋ค.
๋๋ต ํด์ค์ ๊ณ ๋ง์. ๋๋ ์ด ๋ฐฉ๋ฒ์ ์๋ํ๋ค.์ํ ์์ฒด๋ฅผ ์ง์ฐ๋ ๋ฐ์๋ ๋ฌธ์ ๊ฐ ์๋ค.componentWillUnmount์์ ๋๋ ๊ตฌ๋
์ด ๋ผ์ฐํ
๋ณ๊ฒฝ์ ๋ชจ๋ํฐ๋งํ ๋ ์ง์ธ ์ ์๋ค.๋ฌธ์ ๋ ๋ชจ๋ฌ ์ํ๋ฅผ ์ง์ด ํ ํจ๊ณผ์์ ๋น๋๊ธฐ ์์
์ ์ํด ๋ฐํ๋ ๋ฐ์ดํฐ๊ฐ ์๋ค๋ ๊ฒ์
๋๋ค. ์ฌ์ ํ ๋ชจ๋ฌ ์ํ๋ก ๋ค์ ์์ฑ๋์ด ์ด์ ๋น์ฆ๋์ค์ ๋ํฐ ๋ฐ์ดํฐ๊ฐ ์์ฑ๋ฉ๋๋ค.
๊ตฌ๋
์ ๋ผ์ฐํ
๋ณ๊ฒฝ ์ฌํญ์ ๋ชจ๋ํฐ๋งํ๊ธฐ๋ ํฉ๋๋ค.A ํ์ด์ง๋ฅผ ๋๊ฐ ๋ unmodel์ ์ฌ์ฉํ์ฌ ๋ชจ๋ธ A๋ฅผ ์ ๊ฑฐํฉ๋๋ค. ํ์ด์ง A์ ๋ค์ด๊ฐ์ ์๋์ผ๋ก ๋ชจ๋ธ A๋ฅผ ๋ก๋ํ๋ ๊ฒ์ ์ธ๋ชจ๊ฐ ์์ต๋๋ค. ์ด ๋ชจ๋ธ์ด ๋น์ฆ๋์ค์์ ๋ง์ง๋ง์ผ๋ก ์ฌ์ฉ๋์๋์ง ๋๋ ์๋ก ๋ก๋๋ ๋ชจ๋ธ์ธ์ง์ ๊ด๊ณ์์ด ๋ฐ์ดํฐ๊ฐ ๊ธฐ๋ก๋ฉ๋๋ค.
๋ฐ๋ผ์ ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ ๋ชจ๋ธ์ ์ํ๋ฅผ ์ง์ฐ๊ณ ํ์ฌ ๋ค์์คํ์ด์ค์ ๋ชจ๋ ํจ๊ณผ๋ฅผ ์ทจ์ํ๋ ๊ฒ์ด์ง๋ง ํธ์ถํ ๋ฉ์๋๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค. ์กฐ์ธ์ ๊ตฌํ๋ค.
์๋ณธํฌ์คํฐ์ ๋ฌธ์ ๊ฐ ์์ด์ ์ฝคํฌ๋ํธ๋ฅผ ์ธ์ธ์คํจํ์๋ ๋ฏธ์์ฑ ํจ๊ณผ๋ฅผ ์์ ๊ณ ์ถ์๋๋ฐ ๋ฐฉ๋ฒ์ด ์์ด์ ๋๋ฐ์์๋ ์ด๋ฐ API๋ฅผ ์ ๊ณตํ์ง ์๋๋ฏ ํฉ๋๋ค @sorrycc
ํจ๊ณผ๋ฅผ ์ทจ์ํ๊ณ ์ฌ๊ฐ๋ฅผ ๋ถ๋ฆฌํ ์ ์์ต๋๊น?
@dlamon๋ ๊ฐ์ ์ํฉ์ ์ฒํด ๊ฒฝ๋ก๊ฐ ๋ฐ๋์์ ๋ ์ ๋ฆฌ๋ฅผ ์ํ์ต๋๋ค. ์ง๊ธ ํด๊ฒฐ์ฑ ์ด ์์ต๋๊น?
@KyrieChen ์ ๊ฒฝ๋ก ์ ํ ์ค์ ์ ๋ฆฌํ ๊ฒ์ผ๋ก ์์๋์ง ์์ต๋๋ค. ๊ฒฝ๋ก ์ ํ์ด ์๋ฃ๋ ํ ํต์ ์ด ๋์์ค์ง ์์ ์ ์๊ณ , ํต์ ์ด ๋ค์ ๋์์จ ํ์๋ ๋ํฐ ๋ฐ์ดํฐ๊ฐ ์ฌ์ ํ ์ ๋ฆฌ๋ ๋ชจ๋ธ ๋ฐ์ดํฐ ์์ญ์ ๋ค์ ์ฐ๊ธฐ ๋๋ฌธ์ ๋๋ค.
ํ์ฌ ์ ๊ทผ ๋ฐฉ์์ ํธ๋์ญ์
(componentWillMount)์ ์
๋ ฅํ ๋๋ง๋ค ํ์ฌ ํธ๋์ญ์
์ ํด๋นํ๋ ๋ชจ๋ธ ๋ฐ์ดํฐ ์์ญ์ UUID๋ก ํ์ ๋ฐ์ดํฐ ์์ญ์ ์์ฑํ๋ ๊ฒ์ผ๋ก, ํ์ฌ ํธ๋์ญ์
์์ ์ฌ์ฉ๋๋ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ํธ๋์ญ์
์ด ์ข
๋ฃ๋๋ฉด ์ง์์ง๋๋ค(componentWillUnmount). ์๋์ ๋ชจ๋ธ ๊ตฌ์กฐ์ ์ ์ฌํฉ๋๋ค.
ํด๋ฆฌ์ด ๋ชจ๋ธ ์ดํ์ ํต์ ์ด ๋ค์ ์ค๋ฉด ๋ฐ์ดํฐ๋ฅผ ์ธ ๋ ํ์ฌ ๋ฆฌ๋์๊ฐ ์ฌ์ฉํ๋ UUID๊ฐ ์ด์ ํธ๋์ญ์
์์ ์ฌ์ฉ๋ UUID์ด๋ฏ๋ก ๋ํฐ ๋ฐ์ดํฐ๋ ์ด์ ํธ๋์ญ์
์ ๋ฐ์ดํฐ ์์ญ์ ์ฐ์ฌ์ง๊ณ , ๋ค์ ํธ๋์ญ์
์ ์ํด ์์ฑ๋์ง ์์ต๋๋ค.
๊ทธ๋ฌ๋ ์ด ๋ฐฉ๋ฒ๋ ์ข์ง ์์๋ฐ, ์ฒซ์งธ, ๋
ผ๋ฆฌ ๋ณต์ก๋๊ฐ ์ฆ๊ฐํ๊ณ , ๋์งธ ์ด๊ธฐ๊ฐ์ ์ป๊ธฐ ์ํด ๋๊ฐ ํ์ ์ ์ถ๊ฐํด์ผ ํ๋ฏ๋ก ์ฝ๋์ ๋ณต์ก๋๊ฐ ๋์์ง๋ค. ์ ๊ฐ ํ๋ ์ผ์ ์ฃผ๋ก ๊ธ์ต์์คํ
์ ์ํ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ์ด๋ฐ ๋๋ฌ์ด ๋ฐ์ดํฐ๊ฐ ๋ฌด์์์ ์ด ๋ฐฉ๋ฒ์ ์ ํํฉ๋๋ค.
๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ redux-saga์ ์ทจ์ ํจ๊ณผ ๋ฉ์ปค๋์ฆ๊ณผ ๋น์ทํ์ง๋ง dva๋ ์ง๊ธ ์ง์ํ์ง ์๋ ๊ฒ ๊ฐ์ต๋๋ค.
๋ ๋์ ์๋ฃจ์
์ด ์์ผ๋ฉด @ๆ
@dlamon ์ ๋ https://codesandbox.io/s/yqwqpmvwvj
namespace
์์ products
์์ model
effect
๋ฉ์๋์์ ์ทจ์:
dispatch({ type: 'products/@<strong i="10">@CANCEL_EFFECTS</strong>' });
yield sagaEffects.fork(function*() {
yield sagaEffects.take(`${model.namespace}/@@CANCEL_EFFECTS`);
yield sagaEffects.cancel(task);
});
@wss1942 ์ด ๋ฐฉ๋ฒ์ ๋ํด ๋ต๋ณ @CANCEL_EFFECTS '}) ๋ก ์ธํด ํด๋น ๋ชจ๋ฌ์ ํจ๊ณผ๊ฐ ๋ฌดํจ๊ฐ ๋ฉ๋๋ค. #796 ๊ณผ (๊ณผ) ๋น์ทํ
@dlamon dva ๋ ํจ๊ณผ๋ฅผ ์ง์ฐ๋ API๋ฅผ ์ ๊ณตํ์ง ์๋ ๊ฒ ๊ฐ์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ชจ๋ธ์ ์ ์๋ ํจ๊ณผ์ ์ฌ๋ฌ ์ฌ๊ฐ๋ฅผ ์ธ ์ ์์ต๋๋ค.
namespace: 'products',
effects: {
*start(){},
*stop(){},
watchLogin: [
function* ({ take, put, call, cancel, fork, cancelled }) {
yield take('start');
const timerTask = yield fork(timer)
const bgSyncTask = yield fork(bgSync)
yield take('stop')
yield cancel(bgSyncTask)
yield cancel(timerTask)
function* bgSync() {
try {
while (true) {
const result = yield call(delay, 5 * 1000);
yield put({ type: 'stop' })
}
} finally {
if (yield cancelled())
yield put({ type: 'log', payload: 'fetch๐' })
}
}
function* timer(time) {
let i=0;
while (true) {
yield put({ type: 'log', payload: i++ })
yield delay(1000)
}
}
},
{ type: 'watcher' },
],
}
bgSync๋ ๋น๋๊ธฐ ์์
์ด๋ฏ๋ก action: start ๋ก ์์
์ ์์ ํ๊ณ action:stop์ผ๋ก ์์
์
๋ํ ๋น๋๊ธฐ ์์
์ด ๋คํธ์ํฌ ์์ฒญ์ธ ๊ฒฝ์ฐ ๋คํธ์ํฌ ์์ฒญ์ ์ทจ์ํ๋ ์์
๋ ํ์ํ ์ ์๋๋ฐ, ์๋ฅผ ๋ค์ด axios๋ axios.CancelToken์ผ๋ก ์ทจ์ํ ์ ์์ต๋๋ค.
@ws1942 ๊ฐ์ฌํฉ๋๋ค!
์ด๋ฐ ์์ผ๋ก ํจ๊ณผ๋ฅผ ์ทจ์ํ ์ ์์ต๋๋ค. ๋ก๋ฉ ์ํ๋ฅผ ํ์ํ๋ ๊ฒ์ด ๋ ๋ฒ๊ฑฐ๋กญ์ต๋๋ค. ๋ก๋ฉ ์ํ๋ฅผ ํ์ํ๊ธฐ ์ํด dva์ ํจ๊ป ์ ๊ณต๋๋ loading.effects๋ฅผ ์ง์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋ณ๊ฒฝํ๋ ค๋ฉด ์์ ์ ์ฝ๋๋ฅผ ์์ฑํด์ผ ํฉ๋๋ค.
๋๋ ๊ทธ๊ฒ์ ์์ ํ๊ณ ์์ ํ ๋ชจ๋ธ ์ฝ๋๋ฅผ ๊ฒ์ํ์ต๋๋ค.
import { getProduct } from '@/services/Products';
import { isRespSucc, showErrorMsg } from '@/utils/utils';
const initState = {};
export default {
namespace: 'product',
state: initState,
effects: {
/**
ๅจไธคไธช Effects ไน้ด่งฆๅไธไธช็ซ่ต๏ผrace๏ผ
ๅฆๆtaskๅ
็ปๆ๏ผ็ซ่ต็ปๆใ
ๅฆๆtaskๆช็ปๆๆถๆถๅฐcancel๏ผrace effect ๅฐ่ชๅจๅๆถ taskใ
*/
*cancelable({ task, payload }, { call, race, take }) {
yield race({
task: call(task, payload),
cancel: take('cancel'),
});
},
/**
ๅๆถๆๆๆชๅฎๆ็ไปปๅก๏ผๅนถๆง่กๆฐๆฎๆธ
็
*/
*clear(_, { put }) {
yield put.resolve({ type: 'cancel' });
yield put({ type: 'clearState' });
},
*getProduct({ payload }, { call, put, cancelled }) {
// eslint-disable-next-line
yield put.resolve({ type: 'cancelable', task: getProductCancelable, payload });
function* getProductCancelable(params) {
try {
// ่ฐ็จ็ฝ็ป่ฏทๆฑ
const response = yield call(getProduct, params);
// ่ฟๅ็ปๆๅคๆญ
if (!isRespSucc(response)) {
showErrorMsg(response);
return;
}
// ๅๅผ
const { productName } = response.data;
// ่ฐ็จreducerๅญๅผ
yield put({
type: 'saveState',
payload: { productName },
});
} finally {
if (yield cancelled()) {
// TODO: ๅๆถ็ฝ็ป่ฏทๆฑ
}
}
}
},
*getCity(_, { call, put, cancelled }) {
// eslint-disable-next-line
yield put.resolve({ type: 'cancelable', task: getCityCancelable });
function* getCityCancelable() {
// TODO: ๅ
ทไฝๅฎ็ฐ
}
},
reducers: {
saveState(state, { payload }) {
const newState = { ...state, ...payload };
return newState;
},
clearState() {
return initState;
},
},
};
ํธ๋์ญ์ (componentWillUnmount)์ ๋ ๋ ๋ dispatch clear๋ ํ์ฌ ๋ชจ๋ธ์ ๋ฏธ์์ฑ ํจ๊ณผ๋ฅผ ๋ชจ๋ ์ทจ์ํ ์ ์์ผ๋ฉฐ getProductLoading ๋ฐ getCityLoading๋ ์ ์์ ์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
componentWillMount() {
const { dispatch } = this.props;
dispatch({
type: 'product/getProduct',
payload: {
productNumber: '123456',
},
});
dispatch({
type: 'product/getCity',
});
}
componentWillUnmount() {
const { dispatch } = this.props;
dispatch({
type: 'product/clear',
});
}
function mapStateToProps(state) {
return {
getProductLoading: state.loading.effects['product/getProduct'],
getCityLoading: state.loading.effects['product/getCity'],
};
}
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
@ws1942 ๊ฐ์ฌํฉ๋๋ค!
์ด๋ฐ ์์ผ๋ก ํจ๊ณผ๋ฅผ ์ทจ์ํ ์ ์์ต๋๋ค. ๋ก๋ฉ ์ํ๋ฅผ ํ์ํ๋ ๊ฒ์ด ๋ ๋ฒ๊ฑฐ๋กญ์ต๋๋ค. ๋ก๋ฉ ์ํ๋ฅผ ํ์ํ๊ธฐ ์ํด dva์ ํจ๊ป ์ ๊ณต๋๋ loading.effects๋ฅผ ์ง์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋ณ๊ฒฝํ๋ ค๋ฉด ์์ ์ ์ฝ๋๋ฅผ ์์ฑํด์ผ ํฉ๋๋ค.
๋๋ ๊ทธ๊ฒ์ ์์ ํ๊ณ ์์ ํ ๋ชจ๋ธ ์ฝ๋๋ฅผ ๊ฒ์ํ์ต๋๋ค.
ํธ๋์ญ์ (componentWillUnmount)์ ๋ ๋ ๋ dispatch clear๋ ํ์ฌ ๋ชจ๋ธ์ ๋ฏธ์์ฑ ํจ๊ณผ๋ฅผ ๋ชจ๋ ์ทจ์ํ ์ ์์ผ๋ฉฐ getProductLoading ๋ฐ getCityLoading๋ ์ ์์ ์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.