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

时间:2021-03-21 21:03:17

标签: javascript reactjs asynchronous redux redux-saga

最近,我们开始使用 redux-saga 中间件来管理来自商店的异步 API 调用。

以前,我们使用基于通用承诺的操作,一旦我们可以直接在操作本身上使用 async/await.then() 以及 .catch(),这使得管理组件流变得容易。

>

承诺:

const fetchCars = async () => {
  const {data} = await fetchCarsRequest();
  
  setCars(data);
}

cars.map((car) => <li>{car.name}</li>);

关于传奇:

function* fetchCarsSaga() {
  try {
    const {data} = yield call(fetchCarsService);

    yield put(fetchCarsSuccess);
  } catch(error) {
    yield put(fetchCarsFailure);
  } 
}

const fetchCars = async () => {
 fetchCarsRequest(); //action that calls the above saga

 setCars(cars); //state from store 
}

cars.map((car) => <li>{car.name}</li>);

在第二个示例中,即使我们使用生成器来处理异步 API 调用也很困难,但无法使用 await 语句,因此它在 {{1} 之后立即调用 setCars 函数}} 被调用,试图为组件状态设置一些尚不存在的东西。

所以我的问题是:有没有办法替换 fetchCarsRequest 语句并等待请求函数(不是异步函数)完成 API 调用?

2 个答案:

答案 0 :(得分:1)

使用 redux-saga,流程会有所不同。您不直接在组件中使用生成器。您需要从 saga 更新 redux 状态并在组件中获取它。

react component -> redux action -> saga -> redux state -> react component

您可以查看的 PT-BR 中的两篇文章是:

一个好的 create-react-app 模板是:

在代码沙盒中:

答案 1 :(得分:0)

杀死组件状态

您想分派一个操作 #display{ font-family: monospace; } 来触发 API 调用并将结果保存到您的 redux 存储中。您希望等待此操作完成,然后调用 <div id="buttonContainer"> <button data-number="Infinity">Default</button> <button data-number="2">Last Two</button> <button data-number="3">Last Three</button> <button data-number="4">Last Four</button> </div> <hr/> <div id="display"></div> 将您的组件状态设置为来自 redux 状态的值。为什么?

这是一种反模式。数据已经存在于 redux 中,应该直接从组件中的 redux 访问。您应该使用 fetchCarsRequest()setCars(cars) HOC 从 redux 中选择 useSelector 的值。一旦您的提取已分派 connect 并更新商店状态,它会自动使用新数据重新呈现您的组件。

它应该看起来像这样。

传奇

cars

组件

fetchCarsSuccess