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

Reducer返回Pending Promise问题:请求后未收到目标数据对象

Fix: Reducer Receiving Pending Promise Instead of Data Object

Hey there! Let's break down why your reducer is getting a pending Promise instead of the actual API response data, and how to fix it.

The Root Cause

Redux's default behavior expects action creators to return plain action objects immediately. When you return an axios request (which is a Promise) directly from your action creator, the reducer receives that Promise while it's still pending—this is why you see "Action received" logged first, before the "Request" (which fires when the Promise resolves).

Solution: Use Redux Thunk Middleware

Redux Thunk is the most common way to handle asynchronous actions in Redux. It lets your action creators return a function (instead of a plain object), so you can wait for the API request to finish before dispatching the action with actual data.

Step 1: Install Redux Thunk

First, add the package to your project:

npm install redux-thunk
# or
yarn add redux-thunk

Step 2: Configure Your Store to Use Thunk

Update your src/index.js to apply the middleware when creating your Redux store:

import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, applyMiddleware } from 'redux';
import { Provider } from 'react-redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers'; // Import your root reducer
import App from './App';

// Create store with thunk middleware
const store = createStore(
  rootReducer,
  applyMiddleware(thunk)
);

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);

Step 3: Rewrite Your Async Action Creator

Instead of returning a Promise directly, return a function that takes dispatch as an argument. Inside this function, run your axios request, then dispatch the action with the resolved data once the request completes:

// Example action creator (update with your actual API endpoint)
export const fetchSearchResults = (searchTerm) => {
  return (dispatch) => {
    axios.get(`https://your-api-endpoint.com/search?q=${searchTerm}`)
      .then(response => {
        console.log("Request");
        // Dispatch action with the actual data object
        dispatch({
          type: 'FETCH_SEARCH_RESULTS',
          payload: response.data
        });
      })
      .catch(error => {
        // Optional: Dispatch an error action to handle failures
        dispatch({
          type: 'FETCH_SEARCH_FAILED',
          payload: error.message
        });
      });
  };
};

Step 4: Update Your Reducer to Handle the Action

Make sure your reducer correctly processes the action with the data payload:

const initialState = {
  data: null,
  loading: false,
  error: null
};

const searchReducer = (state = initialState, action) => {
  switch(action.type) {
    case 'FETCH_SEARCH_RESULTS':
      console.log("Action received");
      return {
        ...state,
        data: action.payload, // This is now the actual data object
        loading: false,
        error: null
      };
    case 'FETCH_SEARCH_FAILED':
      return {
        ...state,
        loading: false,
        error: action.payload
      };
    // Optional: Add a loading state action if you want to track pending requests
    case 'FETCH_SEARCH_START':
      return {
        ...state,
        loading: true,
        error: null
      };
    default:
      return state;
  }
};

export default searchReducer;

If you're starting fresh or want a cleaner setup, Redux Toolkit is the official recommended approach—it includes Redux Thunk out of the box, plus utilities to simplify action and reducer creation. With createAsyncThunk, your async logic becomes even more concise:

import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';

export const fetchSearchResults = createAsyncThunk(
  'search/fetchResults',
  async (searchTerm) => {
    const response = await axios.get(`https://your-api-endpoint.com/search?q=${searchTerm}`);
    console.log("Request");
    return response.data;
  }
);

const searchSlice = createSlice({
  name: 'search',
  initialState: { data: null, loading: false, error: null },
  extraReducers: (builder) => {
    builder
      .addCase(fetchSearchResults.pending, (state) => {
        state.loading = true;
      })
      .addCase(fetchSearchResults.fulfilled, (state, action) => {
        console.log("Action received");
        state.loading = false;
        state.data = action.payload;
      })
      .addCase(fetchSearchResults.rejected, (state, action) => {
        state.loading = false;
        state.error = action.error.message;
      });
  }
});

export default searchSlice.reducer;

With this setup, your reducer will only receive the action once the API request is complete, giving you the actual data object instead of a pending Promise.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:06:20