You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React:如何在useEffect中从Thunk Dispatch获取数据?

如何获取Redux Thunk异步请求的返回数据

问题背景

我编写了一个用于获取外部API数据的Redux Thunk异步函数,在组件中调用后打印结果得到Promise<pending>,无法拿到实际的返回数据。

异步请求函数代码

export const getServicesFromExternalApi =
  (
    customerNumber: string,
    subcustomer: string | null,
    pickupCountryCode: string,
    pickupPostalCode: string,
    deliveryCountryCode?: string,
    deliveryPostalCode?: string
  ) =>
  (dispatch: ThunkDispatch) => {
    const pickupPostalCodeTrimmed = validTrimmed(pickupPostalCode) ? replace(pickupPostalCode, ' ', '') : null
    const deliveryPostalCodeTrimmed =
      deliveryPostalCode && validTrimmed(deliveryPostalCode) ? replace(deliveryPostalCode, ' ', '') : null

    const servicesUrl = `/api/external/services?customerNo=${
      customerNumber || ''
    }&subcustomer=${subcustomer || ''}&pickupCountryCode=${pickupCountryCode || ''}&pickupPostalCode=${
      pickupPostalCodeTrimmed || ''
    }&deliveryCountryCode=${deliveryCountryCode || ''}&deliveryPostalCode=${deliveryPostalCodeTrimmed || ''}`
    return dispatch(
      asyncRequest(
        fetch(servicesUrl, {
          method: 'GET',
          credentials: 'include',
        }),
        GET_SERVICES
      )
    )
  }

组件中的调用代码

const dispatch = useDispatch()

useEffect(() => {
  const consignment = props.shipment.get('consignments').first()
  const serviceParams = {
      customerNumber: props.shipment.get('custNr'),
      subcustomer: props.shipment.get('custSubcustomer') || '',
      pickupCountryCode: props.shipment.get('pickupCountry'),
      pickupPostalCode: props.shipment.get('pickupZipCode').trim(),
  }
  const services = dispatch(getServicesFromExternalApi(
    serviceParams.customerNumber,
    serviceParams.subcustomer,
    serviceParams.pickupCountryCode,
    serviceParams.pickupPostalCode
  ))
  console.log(services) // 输出 Promise<pending>
})

解决方案

方式一:使用async/await等待Promise完成

Redux Thunk支持返回Promise,因此可以在useEffect内部定义异步函数,通过await等待dispatch的结果:

const dispatch = useDispatch()

useEffect(() => {
  const fetchServices = async () => {
    const consignment = props.shipment.get('consignments').first()
    const serviceParams = {
        customerNumber: props.shipment.get('custNr'),
        subcustomer: props.shipment.get('custSubcustomer') || '',
        pickupCountryCode: props.shipment.get('pickupCountry'),
        pickupPostalCode: props.shipment.get('pickupZipCode').trim(),
    }
    try {
      // 用await等待Promise完成
      const services = await dispatch(getServicesFromExternalApi(
        serviceParams.customerNumber,
        serviceParams.subcustomer,
        serviceParams.pickupCountryCode,
        serviceParams.pickupPostalCode
      ))
      console.log(services) // 这里能拿到实际返回数据
    } catch (err) {
      // 处理请求失败的情况
      console.error('获取服务数据失败:', err)
    }
  }

  fetchServices()
}, [dispatch, props.shipment]) // 务必添加依赖项,避免无限循环

方式二:通过Redux状态订阅获取数据(推荐)

Redux的核心是状态管理,更符合最佳实践的方式是将请求结果存入store,然后在组件中通过useSelector订阅状态:

  1. 确保你的asyncRequest action creator会在请求成功后,将数据更新到Redux store中(比如更新services相关的state字段)
  2. 在组件中订阅状态:
import { useSelector } from 'react-redux'

const dispatch = useDispatch()
// 从store中获取服务数据、加载状态和错误信息
const services = useSelector(state => state.services.data)
const isLoading = useSelector(state => state.services.isLoading)
const requestError = useSelector(state => state.services.error)

useEffect(() => {
  const consignment = props.shipment.get('consignments').first()
  const serviceParams = {
      customerNumber: props.shipment.get('custNr'),
      subcustomer: props.shipment.get('custSubcustomer') || '',
      pickupCountryCode: props.shipment.get('pickupCountry'),
      pickupPostalCode: props.shipment.get('pickupZipCode').trim(),
  }
  dispatch(getServicesFromExternalApi(
    serviceParams.customerNumber,
    serviceParams.subcustomer,
    serviceParams.pickupCountryCode,
    serviceParams.pickupPostalCode
  ))
}, [dispatch, props.shipment])

// 根据状态渲染UI
if (isLoading) return <div>加载中...</div>
if (requestError) return <div>加载失败:{requestError.message}</div>
return (
  <div>
    {/* 在这里渲染services数据 */}
  </div>
)

原因说明

你的getServicesFromExternalApi是一个Thunk函数,调用dispatch(getServicesFromExternalApi(...))会返回一个Promise——因为Thunk内部返回了dispatch(asyncRequest(...)),而asyncRequest封装了异步请求逻辑,本身会返回Promise。直接打印时Promise还处于未完成的pending状态,所以需要通过await或.then()等待它完成,或者通过Redux状态订阅获取最终结果。

内容的提问来源于stack exchange,提问作者Ludwig

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 22:35:15