【发布时间】:2022-01-18 13:51:58
【问题描述】:
我有一个反应组件(用 Typescript 编写),如下所示。
在这个组件中,我尝试读取包含数据的 excel,然后使用数据来渲染组件
由于在useEffect运行之前没有读取数据,所以menuData被初始化为null。
读取数据工作正常,menuData 没有错误。
但是,let meals = [...new Set(menuData.map((item: menuItem) => item.Meal))]; 行抛出错误 TypeError: menuData is undefined。我认为这是因为在 menuData 仍为 undefined 时(在 useEffect 运行之前)执行了此行。
如何克服这个错误?也就是说,let meals = [...new Set(menuData.map((item: menuItem) => item.Meal))];let meals = [...new Set(menuData.map((item: menuItem) => item.Meal))];useEffect 运行后如何运行?
我想将此行保留在 useEffect 之外,因为需要对 menuData 对象数组执行更多的数组函数(map、filter...等)。
export const CategoryItems = ({ toggled }: CategoryItemsProps) => {
const [menuData, setMenuData] = useState<menuData | undefined>(undefined);
/*Code to read the excel with menu items once the page is loaded.
The sheet will be read only once*/
useEffect(() => {
let url = "data.xlsx";
........
....
.....
setMenuData(XLSX.utils.sheet_to_json(worksheet, { raw: true }));
}, []);
let meals = [...new Set(menuData.map((item: menuItem) => item.Meal))];
return (
<div className={`category-items ${toggled ? "theme-dark" : "theme-light"}`}>
.
.
.
//additional code to render the component based on the variable `meals`
.
.
.
</div>
</div>
);
};
【问题讨论】:
-
为什么不把状态初始化为一个空数组呢?
const [menuData, setMenuData] = useState<menuData>([]); -
我假设你的 useEffect 是异步的,所以你不能让它在它之后运行,因为这是将来会发生的事情。但是你可以做的是在 setMenuData 将触发的第二个渲染上运行它。你可以让 menuData 最初为空,但我个人喜欢提前返回 null 选项,如果它不处于要渲染的状态,为什么还要费心处理 JSX。所以在你的
let meals之前,只要做if (!menuData) return null;,你当然可以用某种形式的加载指示器替换null,这取决于你的useEffect 需要多长时间,如果这是你做的事情。 -
@PedroFeltrin 这行得通!如果您想将此作为答案。我会投票赞成。
-
@Keith 我不确定我是否完全理解您的建议。我应该在哪里添加
if (!menuData) return null?在useEffect内? -
@moys 不直接放在你的
let meals之前,基本上在使用useEffect的时候,你一般会做多次渲染,通常不需要第一次渲染,因为你在等待来自的数据useEffect..
标签: javascript use-effect