Next.js天气应用动态路由数据传递报错:TypeError无法读取data属性
动态路由页面无法获取天气数据的类型错误解决方案
问题根源
你在index.js中通过router.push跳转至动态路由页面时,试图依赖首页的weather状态传递数据,但Next.js路由跳转默认不会跨页面共享组件状态,导致hava/[city].jsx中的data为undefined,访问data.data.list[i].dt时触发TypeError。同时,异步数据的传递逻辑不符合Next.js的路由机制,页面刷新或直接访问动态路由时也会出现数据缺失。
解决方案
方案1:动态路由页面独立获取数据(推荐)
让hava/[city].jsx根据路由参数自行请求天气数据,这是Next.js官方推荐的路由数据处理方式:
- 修改
index.js的表单提交逻辑,仅传递城市名称到路由:
// index.js 表单提交函数 const handleSubmit = (e) => { e.preventDefault(); if (!city.trim()) return; router.push(`/hava/${city}`); };
- 在
hava/[city].jsx中,利用路由参数发起数据请求,并处理加载和异常状态:
// hava/[city].jsx import axios from 'axios'; import { useRouter } from 'next/router'; import { useEffect, useState } from 'react'; const WeatherPage = () => { const router = useRouter(); const { city } = router.query; const [weatherData, setWeatherData] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { if (!city) return; const fetchWeather = async () => { try { // 替换为你的OpenWeatherMap API地址和密钥 const response = await axios.get(`https://api.openweathermap.org/data/2.5/forecast?q=${city}&appid=YOUR_API_KEY`); setWeatherData(response.data); } catch (error) { console.error('天气数据获取失败:', error); } finally { setLoading(false); } }; fetchWeather(); }, [city]); // 处理加载和无数据状态 if (loading) return <div>加载中...</div>; if (!weatherData) return <div>未找到该城市的天气信息,请重新搜索</div>; // 渲染天气内容 return ( <div> {weatherData.list.map((item) => ( <div key={item.dt}> {new Date(item.dt * 1000).toLocaleString()} </div> ))} </div> ); }; export default WeatherPage;
方案2:客户端路由跳转时传递状态(仅限临时场景)
若需在客户端跳转时直接传递已获取的数据,可通过router.push的状态参数实现,但页面刷新后状态会丢失:
- 在
index.js中修改跳转逻辑:
// index.js 提交时传递状态 const handleSubmit = async (e) => { e.preventDefault(); try { const response = await axios.get(`https://api.openweathermap.org/data/2.5/forecast?q=${city}&appid=YOUR_API_KEY`); router.push( `/hava/${city}`, undefined, { state: { weatherData: response.data } } ); } catch (error) { console.error('数据获取失败:', error); } };
- 在
hava/[city].jsx中读取状态:
// hava/[city].jsx import { useRouter } from 'next/router'; const WeatherPage = () => { const router = useRouter(); const weatherData = router.state?.weatherData; if (!weatherData) { return <div>数据加载失败,请返回首页重新搜索</div>; } // 渲染天气内容 return ( <div> {weatherData.list.map((item) => ( <div key={item.dt}> {new Date(item.dt * 1000).toLocaleString()} </div> ))} </div> ); }; export default WeatherPage;
关键注意事项
- 永远不要依赖跨路由的组件状态传递数据,Next.js路由页面是独立的,刷新或直接访问时会丢失客户端状态。
- 访问嵌套对象时务必使用可选链操作符(
data?.data?.list?.[i]?.dt),避免因数据未加载完成导致的类型错误。
内容的提问来源于stack exchange,提问作者volfcan
相关产品推荐
相关产品推荐

