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

React+Redux+Hooks项目调用搜索API后渲染结果为undefined如何修复

问题根因梳理

    1. 搜索结果和全量电影共用了同一个Redux状态字段,且数据结构不匹配
      你代码里movies和searchResults都从state.shows取值,而全量电影接口返回的是[{id:xxx, ...}]的扁平结构,搜索接口返回的是[{show: {id:xxx, ...}}]的嵌套结构,两类数据结构不一致,用同一字段存储必然会在遍历的时候取不到对应属性。
    1. 异步搜索请求和状态切换时序错误
      调用dispatch(searchMovieByTitle(searchString))后立刻执行setIsFromSearchResults(true),而Redux thunk的异步请求还未返回,搜索结果还未更新到状态中,此时渲染搜索列表用的还是旧的state.shows数据,自然取不到result.show。
    1. 搜索action里存在无意义的异步处理逻辑
      response.data本身就是同步返回的数组,不需要用map包装再走Promise.all,属于冗余逻辑。

具体修复步骤

第一步:修改Redux Reducer,拆分存储两类数据

你的reducer需要拆分两个字段分别存全量电影和搜索结果,示例如下:

// 你的shows reducer文件
import { FETCH_ALL_SHOWS, SEARCH_MOVIE_BY_TITLE } from '../actions/types';

const initialState = {
  shows: [], // 存全量电影
  searchResults: [] // 单独存搜索结果
}

export default function showsReducer(state = initialState, action) {
  switch(action.type) {
    case FETCH_ALL_SHOWS:
      return {
        ...state,
        shows: action.payload
      }
    case SEARCH_MOVIE_BY_TITLE:
      return {
        ...state,
        searchResults: action.payload
      }
    default:
      return state
  }
}

第二步:修改组件内useSelector的取值逻辑

// 原来的错误写法
// const movies = useSelector((state: RootStateOrAny) => state.shows)
// const searchResults = useSelector((state: RootStateOrAny) => state.shows);

// 修改后
const movies = useSelector((state: RootStateOrAny) => state.shows.shows)
const searchResults = useSelector((state: RootStateOrAny) => state.shows.searchResults);

第三步:修复异步状态切换的时序问题

不要在调用搜索dispatch后立刻切换到搜索结果状态,调整逻辑保证搜索请求完成后再切换状态:

// 1. 先修改搜索action,去掉冗余逻辑,支持promise链式调用
export const searchMovieByTitle = (title: string) => async (dispatch: any) => {
  try {
      let response = await ShowsService.searchMovieByTitle(title);
      dispatch({type: SEARCH_MOVIE_BY_TITLE, payload: response.data});
  } catch (err) {
      console.log(err);
  }
}

// 2. 修改组件内的搜索触发逻辑
const findMovieByTitle = () => {
  setLoading(true);
  // 等待异步请求完成后再切换搜索状态
  dispatch(searchMovieByTitle(searchString)).then(() => {
    setIsFromSearchResults(true);
    setSearchString('');
    setLoading(false);
  });
}

第四步:可选修复分页逻辑

你当前的分页逻辑只会返回最后一页的数据,如果要保留第一页25条的逻辑,直接简化为:

const paginatedArr = movies.slice(0, 25);

如果要做多页切换,额外加currentPage状态配合计算分页区间即可。

可选优化:加空值判断避免报错

遍历搜索结果前加可选链判断,避免数组为空时报错:

{searchResults?.map((result: any, index: number) => {
  // 原有渲染逻辑
})}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 15:33:02