TypeScript React出现defaultValue未传及never类型报错如何解决?
报错解决方案
所有报错的根因是未显式声明TypeScript类型,导致TS无法正确推断状态、Context的结构,按以下步骤修改即可:
步骤1:定义通用类型
先声明Movie数据结构和MovieContext的类型,匹配你的业务字段:
// 匹配OMDB接口返回的电影字段,可根据实际需求扩展 interface Movie { imdbID: string; Title: string; Year: string; Poster: string; isFavorite?: boolean; } // 匹配Context.Provider传递的value结构 interface MovieContextType { setSearch: React.Dispatch<React.SetStateAction<string>>; movies?: Movie[]; favorites: Movie[]; favoriteHandler: (movie: Movie, e: React.FormEvent) => void; showDetail: (id: string) => Promise<void>; selectedMovie: any; // 可单独定义电影详情接口替换any }
步骤2:修复createContext缺少默认值报错
给createContext传入匹配类型的默认值,若你确定外层一定会包裹Provider,也可以用类型断言跳过默认值检查:
// 方式1:补全默认值(推荐) export const MovieContext = createContext<MovieContextType>({ setSearch: () => {}, movies: undefined, favorites: [], favoriteHandler: () => {}, showDetail: async () => {}, selectedMovie: '' }); // 方式2:类型断言跳过默认值检查(适合确定外层有Provider的场景) // export const MovieContext = createContext<MovieContextType>({} as MovieContextType);
步骤3:修复never类型相关报错
给所有useState显式声明类型,覆盖TS默认的never类型推断:
// 明确指定状态类型 const [favorites, setFavorites] = useState<Movie[]>([]); const [movies, setMovies] = useState<Movie[]>(); const [search, setSearch] = useState(''); const [selectedMovie, setSelectedMovie] = useState<any>('');
步骤4:补全函数参数类型
替换冗余的any类型,避免隐式类型报错:
// 给参数加明确类型 const fetchMovies = async (searchValue: string) => { const response = await axios( `https://www.omdbapi.com/?apikey=${API_KEY}&s=${searchValue}` ); const data = response.data; setMovies(data.Search); }; const removeFavoriteMovie = (movie: Movie) => { movie.isFavorite = false; const newFavoriteList = favorites.filter( (fav) => fav.imdbID !== movie.imdbID ); setFavorites(newFavoriteList); }; const addFavoriteMovie = (movie: Movie) => { movie.isFavorite = true; const newFavoriteList = [...favorites, movie]; setFavorites(newFavoriteList); }; const favoriteHandler = (movie: Movie, e: React.FormEvent) => { e.preventDefault(); if (favorites.includes(movie)) { removeFavoriteMovie(movie); } else { addFavoriteMovie(movie); } }; const showDetail = async (id: string) => { const response = await axios( `https://www.omdbapi.com/?apikey=${API_KEY}&i=${id}` ); const data = response.data; setSelectedMovie(data); };
修改后完整代码
import React, { createContext, useState, useEffect, FormEvent } from 'react'; import axios from 'axios'; // 注意:API_KEY请自行提前定义,比如从环境变量取:const API_KEY = import.meta.env.VITE_OMDB_API_KEY interface Movie { imdbID: string; Title: string; Year: string; Poster: string; isFavorite?: boolean; } interface MovieContextType { setSearch: React.Dispatch<React.SetStateAction<string>>; movies?: Movie[]; favorites: Movie[]; favoriteHandler: (movie: Movie, e: FormEvent) => void; showDetail: (id: string) => Promise<void>; selectedMovie: any; } export const MovieContext = createContext<MovieContextType>({ setSearch: () => {}, movies: undefined, favorites: [], favoriteHandler: () => {}, showDetail: async () => {}, selectedMovie: '' }); const MovieApp = ({ children }: { children: React.ReactNode }) => { const [favorites, setFavorites] = useState<Movie[]>([]); const [movies, setMovies] = useState<Movie[]>(); const [search, setSearch] = useState(''); const [selectedMovie, setSelectedMovie] = useState<any>(''); const fetchMovies = async (searchValue: string) => { const response = await axios( `https://www.omdbapi.com/?apikey=${API_KEY}&s=${searchValue}` ); const data = response.data; setMovies(data.Search); }; const removeFavoriteMovie = (movie: Movie) => { movie.isFavorite = false; const newFavoriteList = favorites.filter( (fav) => fav.imdbID !== movie.imdbID ); setFavorites(newFavoriteList); }; const addFavoriteMovie = (movie: Movie) => { movie.isFavorite = true; const newFavoriteList = [...favorites, movie]; setFavorites(newFavoriteList); }; const favoriteHandler = (movie: Movie, e: FormEvent) => { e.preventDefault(); if (favorites.includes(movie)) { removeFavoriteMovie(movie); } else { addFavoriteMovie(movie); } }; const showDetail = async (id: string) => { const response = await axios( `https://www.omdbapi.com/?apikey=${API_KEY}&i=${id}` ); const data = response.data; setSelectedMovie(data); }; useEffect(() => { console.log(API_KEY) fetchMovies(search); }, [search]); return ( <MovieContext.Provider value={{ setSearch, movies, favorites, favoriteHandler, showDetail, selectedMovie, }} > {children} </MovieContext.Provider> ); }; export default MovieApp;
内容的提问来源于stack exchange,提问作者dewilde86
相关产品推荐
相关产品推荐

