TypeScript React中如何正确将对象数组设置到State?
在TypeScript React中正确更新包含对象数组的State
这个报错其实是两个问题叠加导致的:一是没有合并原有状态,二是State的类型没有明确声明,咱们一步步来解决:
1. 理解报错根源
你当前的setState({ fetched_data })会直接替换整个state对象,把原来的menuCatalog和menuCommon属性丢掉了——React的useState不像类组件的setState会自动合并对象,所以TypeScript会提示你新对象缺少必须的属性。另外,初始state里的fetched_data: []被TypeScript推断成了never[](因为没有指定数组元素类型),这也导致你赋值普通对象数组时类型不兼容。
2. 解决步骤
第一步:给State定义明确的类型
先声明一个类型别名或者接口,明确state的结构和每个属性的类型:
// 定义fetched_data里每个元素的类型 interface FetchedItem { id: number; name: string; ip: string; port: number; } // 定义整个state的类型 interface AppState { menuCatalog: boolean; menuCommon: boolean; fetched_data: FetchedItem[]; }
第二步:初始化State时指定类型
在useState里传入泛型参数,让TypeScript知道state的类型:
const [state, setState] = useState<AppState>({ menuCatalog: true, menuCommon: true, fetched_data: [] // 现在这个数组会被推断为FetchedItem[],而不是never[] });
第三步:正确合并状态更新
使用函数式更新或者展开原有state的方式,保留原来的属性,只更新fetched_data:
// 方式一:展开原有state const fetched_stuff = await fetchStuff(); const fetched_data = fetched_stuff["data"]; setState({ ...state, // 保留menuCatalog和menuCommon的当前值 fetched_data // 更新fetched_data }); // 方式二:函数式更新(推荐在依赖原有state的场景下使用,避免闭包问题) setState(prevState => ({ ...prevState, fetched_data: fetched_stuff.data }));
完整示例代码
import { useState, useEffect } from 'react'; interface FetchedItem { id: number; name: string; ip: string; port: number; } interface AppState { menuCatalog: boolean; menuCommon: boolean; fetched_data: FetchedItem[]; } const YourComponent = () => { const [state, setState] = useState<AppState>({ menuCatalog: true, menuCommon: true, fetched_data: [] }); useEffect(() => { const fetchData = async () => { const fetched_stuff = await fetchStuff(); // 假设这是你的异步请求函数 // 函数式更新,确保拿到最新的state setState(prev => ({ ...prev, fetched_data: fetched_stuff.data })); }; fetchData(); }, []); // 组件其他逻辑... return <div>{/* 渲染内容 */}</div>; }; export default YourComponent;
这样处理后,TypeScript的类型检查会通过,同时也不会丢失原有状态的属性啦。
内容的提问来源于stack exchange,提问作者rzar
相关产品推荐
相关产品推荐

