导航到相同的页面,但使用不同的URL查询



我有一个名为List的反应组件,其中有另一个组件称为Places,通过从URL作为道具获取到Places组件后传递数据来显示不同的地方,我有URL,查询为destination,min,maxtype,我在react-router-domLink组件内创建了一个handleType方法swiper-containerdiv内,单击图标后,handleType方法应该采用类型并重新获取数据并仅根据类型显示数据,但是当我这样做时,我得到了一个error message that says "Cannot read properties of null (reading 'destination')"。为什么会发生这种情况?尽管我已经在URL中给出了destination的默认值。

我对React.js有点陌生,3个月新,所以我希望你能帮助我这个

import NavBar from "../../components/navbar/Navbar";
import Header from "../../components/header/Header";
import { Link, useLocation } from "react-router-dom";
import { useState } from "react";
import { format } from "date-fns";
import { DateRange } from "react-date-range";
import SearchItems from "../propertyList/SearchItems";
import Places from "../propertyList/Places";
import {
faBuilding,
faCampground,
faCircleArrowLeft,
faCircleArrowRight,
faFilter,
faHotel,
faHouse,
faSwimmingPool,
} from "@fortawesome/free-solid-svg-icons";
import { Button } from "react-bootstrap";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Swiper, SwiperSlide } from "swiper/react";
import { Navigation, Pagination, Scrollbar, A11y } from "swiper";
import useFetch from "../../hooks/useFetch";
import "swiper/css";
const List = () => {
const location = useLocation();
const [destination, setDestination] = useState(location.state.destination);
const [date, setDate] = useState(location.state.date);
const [openDate, setOpenDate] = useState(false);
const [options, setOptions] = useState(location.state.options);
const [openList, setOpenList] = useState(false);
const [min, setMin] = useState(undefined);
const [max, setMax] = useState();
const [type, setType] = useState(null);
const baseURL = import.meta.env.VITE_REACT_API_URL;
const { data, loading, error, reFetch } = useFetch(
baseURL + `/hotels?city=${destination || ""}&min=${min || 0}&max=${max || 
999}&type=${type || ""}`
);
const handleClick = () => {
reFetch();
};
const handleType = (categoryType) => {
console.log(categoryType);
setType(categoryType);
reFetch();
}
const categories = [
{
id: 1,
name: "house",
icon: <FontAwesomeIcon icon={faHouse} />,
},
{
id: 2,
name: "pool",
icon: <FontAwesomeIcon icon={faSwimmingPool} />,
},
{
id: 3,
name: "camp",
icon: <FontAwesomeIcon icon={faCampground} />,
},
{
id: 4,
name: "apartment",
icon: <FontAwesomeIcon icon={faBuilding} />,
},
{
id: 5,
name: "hotel",
icon: <FontAwesomeIcon icon={faHotel} />,
},
];
return (
<div>
<NavBar />
<div className="categories">
<div className="swiper-button-prev">
<FontAwesomeIcon icon={faCircleArrowLeft} />
</div>
<Swiper
modules={[Navigation]}
spaceBetween={50}
slidesPerView={3}
navigation={{
nextEl: ".swiper-button-next",
prevEl: ".swiper-button-prev",
}}
>
{categories.map((cat,i) => (
<SwiperSlide>
<div className="swiper-container">
<Link onClick={()=>handleType(cat.name)}>
<h2>{cat.icon}</h2>
<span>{cat.name}</span>
</Link>
</div>
</SwiperSlide>
))}
</Swiper>
<div className="swiper-button-next">
<FontAwesomeIcon
icon={faCircleArrowRight}
style={{ color: "#000000" }}
/>
</div>
<Button onClick={() => setOpenList(!openList)}>
<FontAwesomeIcon icon={faFilter} />
<span>Filters</span>
</Button>
</div>
<div className="listContainer">
<div className="listWrapper">
{openList && (
<div className="listSearch">
<h1 className="lsTitle">Search</h1>
<div className="lsItem">
<label>Destination</label>
<input placeholder={destination} type="text" />
</div>
<div className="lsItem">
<label>Check-in Date</label>
<span onClick={() => setOpenDate(!openDate)}>{`${format(
date[0].startDate,
"MM/dd/yyyy"
)} to ${format(date[0].endDate, "MM/dd/yyyy")}`}</span>
{openDate && (
<DateRange
onChange={(item) => setDate([item.selection])}
minDate={new Date()}
ranges={date}
/>
)}
</div>
<div className="lsItem">
<label>Options</label>
<div className="lsOptions">
<div className="lsOptionItem">
<span className="lsOptionText">
Min price <small>per night</small>
</span>
<input
type="number"
onChange={(e) => setMin(e.target.value)}
className="lsOptionInput"
/>
</div>
<div className="lsOptionItem">
<span className="lsOptionText">
Max price <small>per night</small>
</span>
<input
type="number"
onChange={(e) => setMax(e.target.value)}
className="lsOptionInput"
/>
</div>
<div className="lsOptionItem">
<span className="lsOptionText">Adult</span>
<input
type="number"
min={1}
className="lsOptionInput"
placeholder={options.adult}
/>
</div>
<div className="lsOptionItem">
<span className="lsOptionText">Children</span>
<input
type="number"
min={0}
className="lsOptionInput"
placeholder={options.children}
/>
</div>
<div className="lsOptionItem">
<span className="lsOptionText">Room</span>
<input
type="number"
min={1}
className="lsOptionInput"
placeholder={options.rooms}
/>
</div>
</div>
</div>
<button onClick={handleClick}>Search</button>
</div>
)}
<div className="listResult">
<Places items={data} />
</div>
</div>
</div>
</div>
);
};
export default List;

这是用于从后端获取数据的useFetch钩子:

import { useEffect, useState } from "react";
import axios from "axios";
const useFetch = (url) => {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(false);
useEffect(() => {
const fetchData = async () => {
setLoading(true);
try {
const res = await axios.get(url);
setData(res.data);
} catch (error) {
setError(error);
}
setLoading(false);
};
fetchData();
}, []);
const reFetch = async () => {
setLoading(true);
try {
const res = await axios.get(url);
setData(res.data);
} catch (error) {
setError(error);
}
setLoading(false);
};
return { data, loading, error, reFetch };
};
export default useFetch;

state作为prop传递给Link,如下所示:

<Link to="new-path" state={{ some: "value" }} />

你的location.statenull,因为它从来没有设置过。

查看React Router文档获取更多信息。

相关内容

  • 没有找到相关文章