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订阅状态:
- 确保你的
asyncRequestaction creator会在请求成功后,将数据更新到Redux store中(比如更新services相关的state字段) - 在组件中订阅状态:
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
相关产品推荐
相关产品推荐

