React TypeScript报错:Type '() => JSX.Element | undefined' 无法赋值给FC<{}>
React TypeScript类型错误排查与解决
错误信息
Type '() => JSX.Element | undefined' is not assignable to type 'FC<{}>'. Type 'Element | undefined' is not assignable to type 'ReactElement<any, any> | null'. Type 'undefined' is not assignable to type 'ReactElement<any, any> | null'.ts(2322)
问题原因
- 组件返回值可能为undefined:组件首次渲染时,若两个
useEffect还未执行,modifiedCocktail处于初始undefined状态,此时第一个if (!modifiedCocktail)和第二个if (modifiedCocktail)都不触发,组件无返回值,不符合FC要求的ReactElement<any, any> | null类型。 - 类型定义不匹配:
ViewCockTailPros中的ingredients定义为ingredientsProps[](对象数组),但实际代码中赋值的是单个配料字符串/ null组成的数组,类型不兼容。 - useState初始值问题:
useState<ViewCockTailPros|null>()未指定初始值,默认是undefined,与后续逻辑预期的null/有效数据状态不符。
解决方案
1. 修正useState初始值
将modifiedCocktail的初始值设为null,避免初始状态为undefined:
const [modifiedCocktail, setModifiedCocktail] = useState<ViewCockTailPros|null>(null);
2. 简化组件返回逻辑
去掉第二个冗余的if (modifiedCocktail)判断,第一个if (!modifiedCocktail)已经拦截所有无效状态,后续直接解构即可:
// 移除第二个if判断,直接解构 const { name, image, category, info, glass, instructions, ingredients } = modifiedCocktail;
3. 修正类型定义
调整ViewCockTailPros的ingredients类型为(string|null)[],匹配实际赋值的数组类型,同时移除无用的ingredientsProps类型:
export type ViewCockTailPros = { name: string; image: string; info: string; category: string; glass: string; instructions: string; ingredients: (string|null)[]; }
完整修改后的代码
import { FC, useEffect, useState } from "react"; import { useDispatch, useSelector } from "react-redux"; import { Link, useParams } from "react-router-dom"; import { fetchSingleCocktail } from "../redux/features/cocktailSlice"; import { AppDispatch, RootState } from "../redux/store"; export type ViewCockTailPros = { name: string; image: string; info: string; category: string; glass: string; instructions: string; ingredients: (string|null)[]; } const SingleCocktail:FC = () => { const { cocktail } = useSelector((state: RootState) => state.app); const [modifiedCocktail, setModifiedCocktail] = useState<ViewCockTailPros|null>(null); const dispatch = useDispatch<AppDispatch>(); const { id } = useParams(); useEffect(() => { dispatch(fetchSingleCocktail({id})) }, [dispatch, id]); useEffect(() => { if (cocktail && cocktail.length > 0) { const { strDrink: name, strDrinkThumb: image, strAlcoholic: info, strCategory: category, strGlass: glass, strInstructions: instructions, strIngredient1, strIngredient2, strIngredient3, strIngredient4, strIngredient5 } = cocktail[0]; const ingredients = [strIngredient1, strIngredient2, strIngredient3, strIngredient4, strIngredient5]; const newCocktail = { name, image, info, category, glass, instructions, ingredients }; setModifiedCocktail(newCocktail); } else { setModifiedCocktail(null); } }, [cocktail]); if (!modifiedCocktail) { return <h2 className="section-title">No cocktail to display</h2> } const { name, image, category, info, glass, instructions, ingredients } = modifiedCocktail; return ( <> <section className="section cocktail-section"> <Link to={"/"}> <button className="btn btn-danger" style={{marginTop:"2rem"}}>Go Back</button> </Link> <h2 className="section-title">{name}</h2> <div className="drink"> <img src={image} alt={name} /> <div className="drink-info"> <p> <span className="drink-data">Name:</span> {name} </p> <p> <span className="drink-data">Category:</span> {category} </p> <p> <span className="drink-data">Info:</span> {info} </p> <p> <span className="drink-data">Glass:</span> {glass} </p> <p> <span className="drink-data">Instructions:</span> {instructions} </p> <p> <span className="drink-data">Ingredents</span> {ingredients.map((item, index) => { return item ? <span key={index}>{item}</span>:null })} </p> </div> </div> </section> </> ) } export default SingleCocktail
内容的提问来源于stack exchange,提问作者3gwebtrain
相关产品推荐
相关产品推荐

