使用事件处理程序获取 API 的动态路由
2023-11-05
118
我正在尝试创建一个天气应用程序 https://havadurumu-7pqg.vercel.app/ ,并弄清楚如何使用 onSubmit 或 onClick 创建 搜索表单的输入值 的动态路由。
│ pages
│ ├── _app.js
│ ├── _document.js
│ ├── hava
│ │ └── [city].jsx
│ └── index.js
│
index.js
文件(缩短):
export default function Home() {
const [city, setCity] = useState('')
const [weather, setWeather] = useState([]);
const [loading, setLoading] = useState(false);
const router = useRouter();
const fetchWeather = async (e) => {
e.preventDefault();
const axiosRequest = require('axios');
try {
const url = `https://api.openweathermap.org/geo/1.0/direct?q=${city}&&appid=${process.env.NEXT_PUBLIC_WEATHER_KEY}`;
const response = await axiosRequest.get(url);
const url2 = `https://api.openweathermap.org/data/2.5/forecast/daily?lat=${response.data[0].lat}&lon=${response.data[0].lon}&units=metric&cnt=16&appid=${process.env.NEXT_PUBLIC_WEATHER_KEY}`;
const response2 = await axiosRequest.get(url2);
router.push(`/hava/${city}`);
setWeather(response2);
// useEffect(() => {
// console.log(weather.data)
// },[weather]);
} catch (error) {
console.error(error)
}
}
if (loading) {
return <Spinner/>
} else {
return (
<form onSubmit={fetchWeather}
className={'flex justify-between w-full items-center m-auto p-1 bg-transparent border-2 border-gray-400 text-white rounded-2xl'}>
<div>
<input
onChange={(e) => setCity(e.target.value)}
className={'bg-transparent border-none text-gray-600 focus:outline-none text-sm'}
type="text"
placeholder="Search city"/>
</div>
<button type="submit">
<BsSearch size={20}/>
</button>
</form>
</div>
{/*Weather*/}
<div className='lg:mx-auto md:mx-auto overflow-x-auto justify-around container'>
{weather.data && <Weather data={weather}/>}
</div>
);
}
[city].jsx:
const Weather = ({data}) => {
// const router = useRouter();
// const {city} = router.query;
// console.log(data)
let dates =[];
let tempday = [];
let tempnight = [];
let conditions = [];
let description = [];
let aciklama = []
try {
if (data && data.data && data.data.list){
for (let i = 0; i < 16; i++) {
const dt = data.data.list[i].dt;
const options = {month: 'short', weekday: 'short', day: 'numeric'};
const date = new Date(dt * 1000).toLocaleDateString('tr-TR', options);
dates.push(date);
console.log(data.data.list[i].temp.max)
}
for (let i = 0; i < 16; i++) {
const temp = Math.trunc(data.data.list[i].temp.max);
tempday.push(temp);
}
for (let i = 0; i < 16; i++) {
const temp = Math.trunc(data.data.list[i].temp.min);
tempnight.push(temp);
}
for (let i = 0; i < 16; i++) {
const condition = data.data.list[i].weather[0].main;
conditions.push(condition);
}
const city = data.data.city.name;
for (let i = 0; i < 16; i++) {
const desc = data.data.list[i].weather[0].description;
description.push(desc)
}
const aciklama = description.map((desc) => {
switch (desc) {
case "overcast clouds":
return "cok bulutlu";
case "broken clouds":
return "cok bulutlu";
case "scattered clouds":
return "az bulutlu";
case "few clouds":
return "az bulutlu";
case "heavy intensity rain":
return "çok yağmur";
case "moderate rain":
return "yağmurlu";
case "light rain":
return "az yağmur";
case "sky is clear":
return "güneşli";
default:
return desc;
}
});
} catch (error) {
console.error(error)
}
return (
<div className="flex">
<div className='w-[95px]'>
<a className="text-gray-50 text-xs font-bold hover:underline">{dates[0]}</a>
</div>
<div className="max-w-[24px]">
{description[0] === "sky is clear" &&
<Image src={sun} alt='sun-icon'/> || description[0] === "light rain" &&
<Image src={lightrain}
alt='rain-cloud-sun-icon'/> || description[0] === "moderate rain" &&
<Image src={moderaterain}
alt='rain-cloud-icon'/> || description[0] === "heavy intensity rain" &&
<Image src={heavyrain}
alt='rain-cloud-icon'/> || description[0] === "overcast clouds" &&
<Image src={cloud} alt="cloud-sun"/> || description[0] === "broken clouds" &&
<Image src={midcloud} alt="cloud-sun"/> || description[0] === "scattered clouds" &&
<Image src={fewcloud} alt="sun"/> || description[0] === "few clouds" &&
<Image src={fewcloud} alt="sun-cloud-icon"/> || description[0] === "Snow" &&
<Image className="w-3/4" src={snow} alt="snow-icon"/>}
</div>
<div className='pl-2'>
<span
className="p-0.5 text-xs font-normal uppercase tracking-wider text-gray-800 bg-gray-200 rounded-lg bg-opacity-50">{aciklama[0]}
</span>
</div>
</div>
)}
export default Weather
版本
├── [email protected]
├── [email protected]
├── [email protected]
console.log(response2)
"data": {
"city": {
"id": 750269,
"name": "Bursa",
"coord": {
"lon": 29.0675,
"lat": 40.1827
},
},
"list": [
{// the first day of the 16 days of weather forecast
"dt": 1699174800,
"sunrise": 1699159023,
"sunset": 1699196252,
"temp": {
"day": 23.31,
"min": 16.18,
"max": 24.06,
"night": 18.54,
"eve": 22,
"morn": 16.39
},
"pressure": 1010,
"humidity": 44,
"weather": [
{
"id": 501,
"main": "Rain",
"description": "moderate rain",
"icon": "10d"
}
],
当通过在登陆页面上搜索城市提交表单时
"TypeError: Cannot read properties of undefined (reading 'data') at Weather ([city].jsx:30:33)"
提到的错误行“[city].jsx:30:33”如下:
const dt = data.data.list[i].dt;
chatgpt 建议的可能原因:
• 数据正在异步获取,检索数据时出现延迟
• 确保正确定义 Weather 组件以接受 weather 属性
• 确认 Weather 组件正在接收天气状态作为属性
似乎我的 weather.jsx 文件在访问来自 index.js 文件的数据对象时遇到了麻烦。
2个回答
我认为您的
if 语句
不正确
if (!data || !data.data || !data.data.list){}
这表示
if `data` does not exist or
data.data does not exist or
data.data.list does not exist
执行
if
块内的代码。也许此时
data.data
尚未创建。如果您将
if
更改为:
if (data && data.data && data.data.list){}
您的代码应该可以工作
Yilmaz
2023-11-05
已解决
我刚刚将 fetchWeather 函数从 index.js 移至 [city].jsx 文件。然后使用 useState 钩子获取 [city].jsx 文件中的天气,如下所示:
for (let i = 0; i < 16; i++) {
const temp = Math.trunc(weather.list[i].temp.max);
tempday.push(temp);
}
volfcan
2023-11-07