reactjs - React Router 自定义 props 数组无法加载,但自定义字符串可以
我有一个 ReactTS 应用,我通过 Router-Dom-Props 向另一个组件传递一个 prop。问题是我可以单独使用 meal.name,但如果我和 meal.food 一起使用它或者单独使用 meal.food,它就不再工作了。
Uncaught TypeError: meal.food is undefined
我检查了 TypeScript 和 useEffect 错误,但我还没有找到解决方案。
并且 props 在第一次渲染之前加载了吗?
更新 当我像这样使用时 location.state.meal.food 可以打印出 meal.food,但在我通过 useState 设置后就无法使用它——我在 useEffect 中打印了它。
Meal.tsx
return (
<Link className="Meal Link" to={`/MealDetails/${meal.id}`} state={{ meal: meal }}>
<div className="MealIconMealName">
<div className="MealName">{meal.name}</div>
</div>
</Link>
);
};
MealDetails.tsx
const MealDetails = () => {
const location = useLocation();
const navigate = useNavigate();
const [meal, setMeal] = useState(Object);
useEffect(() => {
if (location.state) {
if (location.state.meal) {
setMeal(location.state.meal);
console.log("useEffect" + meal);
}
}
return () => {};
}, [location]);
return (
<div className="MealDetails">
<header>
<div className="HeaderText">{meal.name}</div>
</header>
<div className="MealDetailsCalorieCounter"></div>
{meal.food.map((meal : any) => (
<Food
key={meal.id}
/>
))}
</div>
);
};
从 .json 文件中的示例餐-对象
{
"id": 1,
"name": "Breakfast",
"food": [
{
"name": "Waffeln",
"kcal" : 505
}
],
"calories": 505
}
答案#1
问题
这里的问题似乎是,在初始渲染时,meal.food 未定义,因为 useEffect 钩子还没有将本地组件状态从路由状态(即 location.state)更新过来。
解决方案
在 React 中,将传递的数据和/或派生的“状态”存储在本地组件状态中被认为是一种反模式。直接使用传递的 location.state.meal 路由状态。你还应该使用防御性编程模式,以防用户从路由状态传递以外的任何地方导航到渲染 MealDetails 的路由。
示例:
const MealDetails = () => {
const { state } = useLocation(); // <-- access state
const navigate = useNavigate();
const meal = state || {}; // <-- provide fallback value
return (
<div className="MealDetails">
<header>
<div className="HeaderText">{meal.name}</div>
</header>
<div className="MealDetailsCalorieCounter"></div>
{(meal.food }} []).map((meal: any) => ( // <-- provide fallback array
<Food key={meal.id} />
))}
</div>
);
};
答案#2
我认为这里不需要 useEffect。你可以直接从 location 对象中获取餐点。
const MealDetails = () => {
const location = useLocation();
const { meal } = location.state;
return (
<div className="MealDetails">
<header>
<div className="HeaderText">{meal.name}</div>
</header>
<div className="MealDetailsCalorieCounter"></div>
{meal.food.map((meal : any) => (
<Food
key={meal.id}
/>
))}
</div>
);
};
