如何设置 redux-sagas 和文件结构?

Posted

技术标签:

【中文标题】如何设置 redux-sagas 和文件结构?【英文标题】:how to setup redux-sagas and file structure? 【发布时间】:2018-09-17 02:57:49 【问题描述】:

在我学习如何安装 jwt 并应用于我的 React native 之后,我正在使用 React-native、axios .所以我研究了一下redux, redux-thunk, redux-saga,然后我选择了redux-saga

任何人都可以指导我设置 redux-sagas 之类的文件夹结构,代码拆分示例,我有 2 个页面,例如产品,固件。

在 redux-thunk 中

action/
      /actionProduct.js
      /actionFirmware.js
reducer/
       /index.js
       /productReducer.js
       /firmwareReducer.js
store.js
index.js

但在 redux-sagas 中我开始感到困惑 它有 action、reducer、sagas 和 store 也是不同的设置。

const sagaMiddleware = createSagaMiddleware();
// mount it on the Store
const store = createStore(reducer, applyMiddleware(sagaMiddleware));

// then run the saga
sagaMiddleware.run(mySaga);
export default store;

在 redux-thunk 中我从未见过像这样的类似语法 sagaMiddleware.run(mySaga);

我需要创建 sagas 文件夹并添加 2 个 sagas,例如 productSagas、firmwareSagas 吗?

我需要写两行吗

sagaMiddleware.run(productSagas);
sagaMiddleware.run(firmwareSagas);
export default store;

或者我们可以设置动态存储?我该怎么做? 提前致谢。


新话题

我不确定我是否已正确设置此设置或不让查看我的设置。 Store.js

const sagaMiddleware = createSagaMiddleware();
const store = createStore(
  rootReducer,
  window.devToolsExtension && process.env.NODE_ENV !== 'production' ?
  compose(
    applyMiddleware(sagaMiddleware),
    window.devToolsExtension(),
  ) :
  applyMiddleware(sagaMiddleware),
);

sagaMiddleware.run(rootSaga);

export default store;

rootSaga 文件

export default function* rootSaga() 
    yield all([
        firmwareWatcher(),
        productWatcher(),
    ]);

rootReducer

export default const rootReducer = combineReducers(
    firmware,
    porduct,
);

App.js

class App extends Component 
  componentDidMount() 
    const  dispatch  = this.props; 
    dispatch( type: "FIRMWARE_REQUEST");
    dispatch( type: 'PRODUCT_REQUEST');
  
....

const mapStateToProps = (state) => 
  console.log(state);
  return  ... ;
;

这是我得到的 mapStateToProps 中的 console.log(state),我在 switch case 中使用 consone.log 来了解 ACTION TYPE

    PRODUCT_SUCCESS
        type: "PRODUCT_SUCCESS", payload: …, @@redux-saga/SAGA_ACTION: true
        firmware: …, porduct: …
    FIRMWARE_SUCCESS
        type: "API_CALL_SUCCESS", payload: …, @@redux-saga/SAGA_ACTION: true
    default
        firmware: …, porduct: …
    firmware: …, porduct: …
  |
  V
firmware : fetching: false, dog: null, error: null, data: "https://dog.ceo/api/img/retriever-golden/n02099601_2495.jpg"
porduct :
    data : id: 120, name: "A1", image: "a1_12-16-2017-1513389068.jpg", price: "28.00", status: 1, …

【问题讨论】:

【参考方案1】:

您不需要运行单个 saga,因为您使用的是 sagaMiddleware,所以您的所有操作都将通过您的 saga。我认为你在正确的轨道上 - 这是我设置 sagas 的方式。

为每个异步组件创建一个 saga,productSaga.jsfirmwareSaga.js

然后为您的 sagas index-sagas.js 创建一个索引文件。这将从您的项目中导入所有 sagas 并将它们导出以在您的 index.js 文件中使用。

/// index-sagas.js ///
import productWatcher from './components/product/product-saga.js';
import firmwareWatcher from './components/firmware/firmware-saga.js';

export default function* IndexSagas() 
  yield [
    productWatcher(),
    firmwareWatcher(),
  ]

/// end of file ///

这是您在index.js 顶部导入的内容:

/// index.js ///
import IndexSagas from './index-sagas.js'

...

/// end of file ///

product-saga.jsfirmware-saga.js 中创建一对生成器函数

/// product-saga.js ///
import  PRODUCT_ACTION  from './constants';
import  productActionSuccess, productActionError  from './actions';

export default function* productWatcher() 
  yield [
    takeLatest(PRODUCT_ACTION, productActionFlow)
  ]
 
// This will be triggered any time PRODUCT_ACTION is dispatched and it
// will call the productActionFlow generator.  This is
// where your async logic lives  

function* productActionFlow(action) 
  try 
    const result = yield call(productGETRequest, action)
    // productGETRequest is a function elsewhere in this file that
    // will make your GET request
    yield put(productActionSuccess(result))
    // productActionSuccess is the action imported above
   catch (error) 
    yield put(productActionError(error)
  

【讨论】:

Keller 看,它看起来像 Sagas 设置,比如 reducer 有 rootReducer 并将所有 saga 导入到 root。但是为什么要将 IndexSagas 导入 index.js 呢?我们是否将包含 store.js 中所有 saga 的 IndexSagas 导入到 sagaMiddleware.run(IndexSagas);right ? Reaksmey,您将 IndexSagas 导入 index.js,因为需要告知 sagaMiddleware 项目中所有 sagas 的位置——它不会去寻找它们。你在你的 index.js 中告诉 sagaMiddleware 这个信息,如下所示: --继续--sagaMiddleware.run(IndexSagas);。如果您愿意,您也许可以运行每个单独的 saga,但这更简洁一些。我不相信sagaMiddleware.run(indexSagas); 会对您的商店进行任何更改。到那时你应该已经这样做了:const store = createStore(reducer, applyMiddleware(sagaMiddleware)); 帮助检查我上面的答案编辑是否正确?毕竟感谢您的帮助。 Product Saga 和 Index Sagas 只是函数生成器,与 redux-saga 无关,需要连接 saga 中间件。这只是组织代码。很好的答案卢卡斯!

以上是关于如何设置 redux-sagas 和文件结构?的主要内容,如果未能解决你的问题,请参考以下文章

使用 redux-saga 作为中间件,在 root saga 文件中使用的 All 效果和 Fork 效果都比较有用

P18:Redux-saga获取TodoList列表

P17:Redux-saga 的安装和配置

如何使用 Redux-Saga 和 Hooks 调用 API

redux-saga

如何使用 redux-saga 处理异步 API 调用?