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

React+TypeScript中useReducer状态更新类型错误排查求助

React useReducer状态赋值类型不匹配问题

问题代码与错误信息

自定义Hook代码

import React, { useReducer, useEffect } from 'react';
import { v4 as uuid } from 'uuid';

import { Movie, MoviesAction } from 'types';
import { getMovies } from 'api/movies';

interface MoviesState {
  movies: Movie[]
  initialized: boolean
}

export function useMoviesCollection(): [MoviesState, React.Dispatch<MoviesAction>] {
  const movieReducer = (state: MoviesState, action: MoviesAction): MoviesState => {
    switch (action.type) {
      case 'fetch':
          return { ...state, movies: action.payload };
      case 'add':
        return { ...state };
      case 'delete':
        return { ...state };
      case 'rate':
        return { ...state };
      default:
        return state
    }
  };

  const [state, dispatch] = useReducer(movieReducer, {
    movies: [],
    initialized: false,
  });

  useEffect( () => {
     getMovies().then((d)=>{
         dispatch({
          type: 'fetch',
          payload: {
              data: d
          }
      })
     })
  }, []);

  return [state, dispatch];
}

API实现

import { Movie } from "types"

export const getMovies = async (): Promise<Movie[]> => {
    return require('../data/movies.json')
}

类型定义

export interface Movie {
    id: string,
    title: string,
    subtitle: string,
    description: string,
    imageUrl: string,
    ratings: number[]
}

export interface MovieFetchAction {
    type: 'fetch',
    payload: {
        data: Movie[]
    }
}

错误信息

Type '{ data: Movie[]; }' is missing the following properties from type 'Movie[]': length, pop, push, concat, and 28 more. 

错误原因

在movieReducer的fetch分支中,你尝试将action.payload直接赋值给state.movies,但根据MovieFetchAction的定义,action.payload是包含data字段的对象(类型为{ data: Movie[] }),而state.movies需要的是Movie[]类型,两者类型不匹配,触发TypeScript类型检查错误。

修复方案

两种可行修复方式任选其一:

方案1:修改reducer逻辑,提取payload中的data

直接在reducer里获取action.payload.data赋值给movies,同时可将initialized设为true标记数据加载完成:

case 'fetch':
  return { ...state, movies: action.payload.data, initialized: true };

方案2:简化Action的payload类型

如果不需要嵌套的data字段,可调整类型定义和dispatch传参:

  1. 修改MovieFetchAction的payload类型:
export interface MovieFetchAction {
    type: 'fetch',
    payload: Movie[]
}
  1. 调整useEffect中的dispatch代码:
getMovies().then((d)=>{
    dispatch({
        type: 'fetch',
        payload: d
    })
})
  1. reducer中的fetch分支保持原逻辑即可:
case 'fetch':
  return { ...state, movies: action.payload, initialized: true };

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 06:25:17