Dva: ํšจ๊ณผ ์ทจ์†Œ ๋ฐฉ๋ฒ•

์— ๋งŒ๋“  2018๋…„ 06์›” 08์ผ  ยท  11์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: dvajs/dva

๋ฌธ์ œ๋ฅผ ์žฌํ˜„ํ•˜๋Š” ์ฝ”๋“œ: (์žฌ์ƒ ๊ฐ€๋Šฅํ•œ ์ฝ”๋“œ ๋˜๋Š” ๋‹จ๊ณ„๋ฅผ ์ œ๊ณตํ•˜์„ธ์š”.)

์‹œ๋‚˜๋ฆฌ์˜ค: ํ”„๋กœ์ ํŠธ์— ๋ชจ๋ธ 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

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

@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'],
    };
  }

๋ชจ๋“  11 ๋Œ“๊ธ€

๋ชจ๋ธ ๊ตฌ๋…์—์„œ ๋ผ์šฐํŒ… ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๊ณ  ํŽ˜์ด์ง€๊ฐ€ A ํŽ˜์ด์ง€๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ(A ํŽ˜์ด์ง€ ๋‚˜๊ฐ€๊ธฐ) ๋˜๋Š” A ํŽ˜์ด์ง€(A ํŽ˜์ด์ง€ ์ž…๋ ฅ)์ธ ๊ฒฝ์šฐ ๋ชจ๋ธ A์˜ ์ƒํƒœ๋ฅผ ์ˆ˜๋™์œผ๋กœ ์ง€์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋Œ€๋‹ต ํ•ด์ค˜์„œ ๊ณ ๋งˆ์›Œ. ๋‚˜๋Š” ์ด ๋ฐฉ๋ฒ•์„ ์‹œ๋„ํ–ˆ๋‹ค.์ƒํƒœ ์ž์ฒด๋ฅผ ์ง€์šฐ๋Š” ๋ฐ์—๋Š” ๋ฌธ์ œ๊ฐ€ ์—†๋‹ค.componentWillUnmount์—์„œ ๋˜๋Š” ๊ตฌ๋…์ด ๋ผ์šฐํŒ… ๋ณ€๊ฒฝ์„ ๋ชจ๋‹ˆํ„ฐ๋งํ•  ๋•Œ ์ง€์šธ ์ˆ˜ ์žˆ๋‹ค.๋ฌธ์ œ๋Š” ๋ชจ๋‹ฌ ์ƒํƒœ๋ฅผ ์ง€์šด ํ›„ ํšจ๊ณผ์—์„œ ๋น„๋™๊ธฐ ์ž‘์—…์— ์˜ํ•ด ๋ฐ˜ํ™˜๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์—ฌ์ „ํžˆ ๋ชจ๋‹ฌ ์ƒํƒœ๋กœ ๋‹ค์‹œ ์ž‘์„ฑ๋˜์–ด ์ด์ „ ๋น„์ฆˆ๋‹ˆ์Šค์˜ ๋”ํ‹ฐ ๋ฐ์ดํ„ฐ๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.
๊ตฌ๋…์˜ ๋ผ์šฐํŒ… ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.A ํŽ˜์ด์ง€๋ฅผ ๋‚˜๊ฐˆ ๋•Œ unmodel์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋ธ A๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. ํŽ˜์ด์ง€ A์— ๋“ค์–ด๊ฐ€์„œ ์ˆ˜๋™์œผ๋กœ ๋ชจ๋ธ A๋ฅผ ๋กœ๋“œํ•˜๋Š” ๊ฒƒ์€ ์“ธ๋ชจ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ด ๋ชจ๋ธ์ด ๋น„์ฆˆ๋‹ˆ์Šค์—์„œ ๋งˆ์ง€๋ง‰์œผ๋กœ ์‚ฌ์šฉ๋˜์—ˆ๋Š”์ง€ ๋˜๋Š” ์ƒˆ๋กœ ๋กœ๋“œ๋œ ๋ชจ๋ธ์ธ์ง€์— ๊ด€๊ณ„์—†์ด ๋ฐ์ดํ„ฐ๊ฐ€ ๊ธฐ๋ก๋ฉ๋‹ˆ๋‹ค.
๋”ฐ๋ผ์„œ ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์€ ๋ชจ๋ธ์˜ ์ƒํƒœ๋ฅผ ์ง€์šฐ๊ณ  ํ˜„์žฌ ๋„ค์ž„์ŠคํŽ˜์ด์Šค์˜ ๋ชจ๋“  ํšจ๊ณผ๋ฅผ ์ทจ์†Œํ•˜๋Š” ๊ฒƒ์ด์ง€๋งŒ ํ˜ธ์ถœํ•  ๋ฉ”์„œ๋“œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์กฐ์–ธ์„ ๊ตฌํ•˜๋‹ค.

์›๋ณธํฌ์Šคํ„ฐ์— ๋ฌธ์ œ๊ฐ€ ์žˆ์–ด์„œ ์ฝคํฌ๋„ŒํŠธ๋ฅผ ์–ธ์ธ์Šคํ†จํ–ˆ์„๋•Œ ๋ฏธ์™„์„ฑ ํšจ๊ณผ๋ฅผ ์—†์• ๊ณ  ์‹ถ์—ˆ๋Š”๋ฐ ๋ฐฉ๋ฒ•์ด ์—†์–ด์„œ ๋“œ๋ฐ”์—์„œ๋Š” ์ด๋Ÿฐ API๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š”๋“ฏ ํ•ฉ๋‹ˆ๋‹ค @sorrycc

ํšจ๊ณผ๋ฅผ ์ทจ์†Œํ•˜๊ณ  ์‚ฌ๊ฐ€๋ฅผ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

@dlamon๋„ ๊ฐ™์€ ์ƒํ™ฉ์— ์ฒ˜ํ•ด ๊ฒฝ๋กœ๊ฐ€ ๋ฐ”๋€Œ์—ˆ์„ ๋•Œ ์ •๋ฆฌ๋ฅผ ์›ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ ํ•ด๊ฒฐ์ฑ…์ด ์žˆ์Šต๋‹ˆ๊นŒ?

@KyrieChen ์€ ๊ฒฝ๋กœ ์ „ํ™˜ ์ค‘์— ์ •๋ฆฌํ•  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ฒฝ๋กœ ์ „ํ™˜์ด ์™„๋ฃŒ๋œ ํ›„ ํ†ต์‹ ์ด ๋Œ์•„์˜ค์ง€ ์•Š์„ ์ˆ˜ ์žˆ๊ณ , ํ†ต์‹ ์ด ๋‹ค์‹œ ๋Œ์•„์˜จ ํ›„์—๋„ ๋”ํ‹ฐ ๋ฐ์ดํ„ฐ๊ฐ€ ์—ฌ์ „ํžˆ ์ •๋ฆฌ๋œ ๋ชจ๋ธ ๋ฐ์ดํ„ฐ ์˜์—ญ์— ๋‹ค์‹œ ์“ฐ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

ํ˜„์žฌ ์ ‘๊ทผ ๋ฐฉ์‹์€ ํŠธ๋žœ์žญ์…˜(componentWillMount)์„ ์ž…๋ ฅํ•  ๋•Œ๋งˆ๋‹ค ํ˜„์žฌ ํŠธ๋žœ์žญ์…˜์— ํ•ด๋‹นํ•˜๋Š” ๋ชจ๋ธ ๋ฐ์ดํ„ฐ ์˜์—ญ์— UUID๋กœ ํ•˜์œ„ ๋ฐ์ดํ„ฐ ์˜์—ญ์„ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์œผ๋กœ, ํ˜„์žฌ ํŠธ๋žœ์žญ์…˜์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ํŠธ๋žœ์žญ์…˜์ด ์ข…๋ฃŒ๋˜๋ฉด ์ง€์›Œ์ง‘๋‹ˆ๋‹ค(componentWillUnmount). ์•„๋ž˜์˜ ๋ชจ๋ธ ๊ตฌ์กฐ์™€ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค.
2018-11-07 7 25 31
ํด๋ฆฌ์–ด ๋ชจ๋ธ ์ดํ›„์— ํ†ต์‹ ์ด ๋‹ค์‹œ ์˜ค๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ ์“ธ ๋•Œ ํ˜„์žฌ ๋ฆฌ๋“€์„œ๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” 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'],
    };
  }
์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰