代码之家  ›  专栏  ›  技术社区  ›  SimonEritsch

如果注入不同容器,Redux传奇会多次开火

  •  6
  • SimonEritsch  · 技术社区  · 8 年前

    我们正在使用 https://github.com/react-boilerplate/react-boilerplate 并具有多个组件的经典店铺布局。

    我们有一个redux商店,用于将产品添加到购物车,这有一个副作用,可以将添加的产品保存到购物车数据库。

    因为有多个位置可以向购物车添加产品,所以我们在一个页面上使用了相同的CartContainer三次(购物车本身、产品列表和另一个产品列表)。

    我们现在的问题是,api将被调用3次。

    我想这是因为,通过使用容器三次,我们也注入了传奇三次。

    我现在的问题是: 只有一次注入传奇故事,而不必一次又一次重写所有传奇故事的正确方法是什么?

    这是我的传奇:

    import {
      call,
      put,
      select,
      takeLatest,
    } from 'redux-saga/effects';
    import {getRequest, putRequest} from '../../utils/request';
    
    import {ADD_PRODUCT, LOAD_PRODUCTS} from './constants';
    import {
      addProductSuccess,
      addProductError,
      productsLoaded,
      productsLoadingError,
    } from './actions';
    import {makeSelectProduct, makeSelectUserId} from './selectors';
    
    
    /**
     * Github repos request/response handler
     */
    export function* getProducts() {
      const requestURL = '/api/orders';
      const user_id = yield select(makeSelectUserId());
      try {
        let itemsData = yield call(getRequest, requestURL, user_id);
        if (itemsData) {
          itemsData = itemsData.slice(-1).items;
        }
        yield put(productsLoaded(itemsData));
      } catch (err) {
        yield put(productsLoadingError(err));
      }
    }
    
    /**
     * Github repos request/response handler
     */
    export function* addProduct() {
      const requestURL = '/api/cart';
      const productData = yield select(makeSelectProduct());
    
      try {
        const orderData = yield call(putRequest, requestURL, productData);
        yield put(addProductSuccess(orderData.id));
      } catch (err) {
        yield put(addProductError(err));
      }
    }
    
    /**
     * Root saga manages watcher lifecycle
     */
    export default function* root() {
      yield [
        takeLatest(ADD_PRODUCT, addProduct),
        takeLatest(LOAD_PRODUCTS, getProducts),
      ];
    }
    

    这是我的集装箱的出口部分:

    export function mapDispatchToProps(dispatch) {
      return {
        onAddProduct: (id, quantity, variant) => {
          dispatch(addProduct(id, quantity, variant));
        },
        onLoadProducts: (user_id) => {
          dispatch(loadProducts(user_id));
        },
      };
    }
    
    const mapStateToProps = createStructuredSelector({
      products: makeSelectProducts(),
    });
    
    const withConnect = connect(mapStateToProps, mapDispatchToProps);
    
    const withReducer = injectReducer({key: 'cart', reducer});
    const withSaga = injectSaga({key: 'cart', saga});
    
    
    export default compose(withReducer, withConnect)(CartContainer);
    
    2 回复  |  直到 8 年前
        1
  •  6
  •   soupette    8 年前

    你必须改变注入传奇的方式,使其只注入一次。

    在您的 containers/App/index.js

    // ...
    import { compose } from 'redux';
    import injectSaga from 'utils/injectSaga';
    import injectReducer from 'utils/injectReducer';
    import reducer from 'containers/CartContainer/reducer';
    import saga from 'containers/CartContainer/saga';
    
    function App() { // We don't change this part
      // ...
    }
    
    
    // Add this lines
    const withReducer = injectReducer({ key: 'cartContainer', reducer });
    const withSaga = injectSaga({ key: 'cartContainer', saga });
    
    export default compose(
      withReducer,
      withSaga,
    )(App);
    

    现在在您的“containers/CartContainer/index”中。js公司``

    import React from 'react':
    
    // ...
    
    class CartContainer extends React.Component {
      // ...
    }
    
    const withConnect = connect(mapStateToProps, mapDispatchToProps);
    
    // REMOVE THIS LINES //
    // const withReducer = injectReducer({ key: 'cartContainer', reducer });
    // const withSaga = injectSaga({ key: 'cartContainer', saga });
    
    export default compose(
     // withReducer,
     // withSaga,
     withConnect,
    )(CartContainer);
    
        2
  •  2
  •   Krasimir    8 年前

    我猜你在用 redux-sagas-injector 这在我看来总是很奇怪。这个传奇故事在React组件内部或周围都没有立足之地。在我看来,这是一种反模式。您的组件应该只调度动作,而监听这些动作的传奇应该只处理副作用。我建议在一个地方初始化redux存储,不要使用 injectReducer injectSaga .

    附笔。 抱歉,但我觉得这看起来很奇怪 mapDispatchToProps mapStateToProps .