如何过滤使用 useEffect 显示的内容?
How can I filter through what is displayed with useEffect?
我有点不知道下一步要做什么。我设法显示了内容,但我似乎无法通过单击来过滤它。使用不同的 api 很容易,我遵循了 webdevsimplified 但这我无法解决,我无能为力!
我只想过滤映射的 api。例如,如果我选中 3,它应该只显示 3 starRating。谁能给我一些建议。
App.js
import { useEffect, useState, useRef } from 'react'
import Header from './components/Header';
import SearchBar from './components/SearchBar';
export default function App() {
const [hotelRooms, setHotelRooms] = useState([]);
const fetchHotels = async () => {
const res = await fetch('https://obmng.dbm.guestline.net/api/hotels?collection-id=OBMNG')
const hotels = await res.json()
const hotelRooms = []
for(const hotel of hotels) {
const res = await fetch(`https://obmng.dbm.guestline.net/api/roomRates/OBMNG/${hotel.id}`)
const info = await res.json()
hotelRooms.push({ hotel, rooms: info.rooms })
}
setHotelRooms(hotelRooms)
}
useEffect(() => {
fetchHotels()
}, [])
return (
<div className="App">
<Header/>
{
hotelRooms.map(h => (
<div>
<input value={"1"} type="checkbox" onChange={}/>
<input value={"Adults"}type="checkbox" onChange={}/>
<h2> Name: {h.hotel.name}</h2>
<p> Description: {h.hotel.description}</p>
<p> Rating: {h.hotel.starRating}</p>
<p> Postcode: {h.hotel.postcode}</p>
<p> City: {h.hotel.town}</p>
<img src={h.hotel.images}/>
<p style={{ fontWeight: 'bold' }}>Rooms:</p>
{
h.rooms.map(room => (
<div>
<h5>Occupancy</h5>
<div> Adults: {room.occupancy.maxAdults}</div>
<div> Children: {room.occupancy.maxChildren}</div>
<div> Maximum guests: {room.occupancy.maxOverall}</div>
<div> Room type: {room.name}</div>
<img src={room.images}/>
</div>
))
}
</div>
))
}
</div>
);
}
如果我没有正确理解您的问题,您希望它在更新 hotelRooms 后重新呈现吗?如果这是正确的,当你第一次渲染它时,值为 [],一个空数组。在这里:
useEffect(() => {
fetchHotels()
}, [])
最后一点 [],在渲染后运行一次。因此,在您的情况下(如果我的假设是正确的),您需要将其更改为,因为您希望它在每次 hotelRooms 值更改时重新呈现
useEffect(() => {
fetchHotels()
}, [hotelRooms])
您应该有一个保存筛选属性的状态。
const [filter, setFilter] = useState({ ratings: ["1", "2", "3", "4", "5"] });
显示复选框时,为它们添加名称和相应的值。
请记住,当您在渲染中使用 .map
时,将唯一键添加到最外面的标签。
<div>
{["1", "2", "3", "4", "5"].map((star) => (
<div key={"input-" + star}>
<input
id={"rated" + star}
value={star}
name="ratings"
type="checkbox"
checked={filter.ratings.includes(star)}
onChange={handleRatingFilter}
/>
<label htmlFor={"rated" + star}>Rated {star} star</label>
</div>
))}
</div>
现在在 onChange
处理程序中,根据复选框更新状态:
const handleRatingFilter = (e) => {
if (e.target.checked) {
// adding value
const temp = [...filter.ratings];
temp.push(e.target.value);
setFilter({ ...filter, ratings: temp });
} else {
// removing value
setFilter({
...filter,
ratings: [...filter.ratings.filter((v) => v !== e.target.value)]
});
}
};
最后,当您在 hotelRooms
上使用 .map
时,您可以在映射之前过滤列表。
{hotelRooms
.filter((h) => filter.ratings.includes(h.hotel.starRating))
.map((h) => (
<div key={h.hotel.name}>
stuff
</div>
))
}
我有点不知道下一步要做什么。我设法显示了内容,但我似乎无法通过单击来过滤它。使用不同的 api 很容易,我遵循了 webdevsimplified 但这我无法解决,我无能为力!
我只想过滤映射的 api。例如,如果我选中 3,它应该只显示 3 starRating。谁能给我一些建议。
App.js
import { useEffect, useState, useRef } from 'react'
import Header from './components/Header';
import SearchBar from './components/SearchBar';
export default function App() {
const [hotelRooms, setHotelRooms] = useState([]);
const fetchHotels = async () => {
const res = await fetch('https://obmng.dbm.guestline.net/api/hotels?collection-id=OBMNG')
const hotels = await res.json()
const hotelRooms = []
for(const hotel of hotels) {
const res = await fetch(`https://obmng.dbm.guestline.net/api/roomRates/OBMNG/${hotel.id}`)
const info = await res.json()
hotelRooms.push({ hotel, rooms: info.rooms })
}
setHotelRooms(hotelRooms)
}
useEffect(() => {
fetchHotels()
}, [])
return (
<div className="App">
<Header/>
{
hotelRooms.map(h => (
<div>
<input value={"1"} type="checkbox" onChange={}/>
<input value={"Adults"}type="checkbox" onChange={}/>
<h2> Name: {h.hotel.name}</h2>
<p> Description: {h.hotel.description}</p>
<p> Rating: {h.hotel.starRating}</p>
<p> Postcode: {h.hotel.postcode}</p>
<p> City: {h.hotel.town}</p>
<img src={h.hotel.images}/>
<p style={{ fontWeight: 'bold' }}>Rooms:</p>
{
h.rooms.map(room => (
<div>
<h5>Occupancy</h5>
<div> Adults: {room.occupancy.maxAdults}</div>
<div> Children: {room.occupancy.maxChildren}</div>
<div> Maximum guests: {room.occupancy.maxOverall}</div>
<div> Room type: {room.name}</div>
<img src={room.images}/>
</div>
))
}
</div>
))
}
</div>
);
}
如果我没有正确理解您的问题,您希望它在更新 hotelRooms 后重新呈现吗?如果这是正确的,当你第一次渲染它时,值为 [],一个空数组。在这里:
useEffect(() => {
fetchHotels()
}, [])
最后一点 [],在渲染后运行一次。因此,在您的情况下(如果我的假设是正确的),您需要将其更改为,因为您希望它在每次 hotelRooms 值更改时重新呈现
useEffect(() => {
fetchHotels()
}, [hotelRooms])
您应该有一个保存筛选属性的状态。
const [filter, setFilter] = useState({ ratings: ["1", "2", "3", "4", "5"] });
显示复选框时,为它们添加名称和相应的值。
请记住,当您在渲染中使用 .map
时,将唯一键添加到最外面的标签。
<div>
{["1", "2", "3", "4", "5"].map((star) => (
<div key={"input-" + star}>
<input
id={"rated" + star}
value={star}
name="ratings"
type="checkbox"
checked={filter.ratings.includes(star)}
onChange={handleRatingFilter}
/>
<label htmlFor={"rated" + star}>Rated {star} star</label>
</div>
))}
</div>
现在在 onChange
处理程序中,根据复选框更新状态:
const handleRatingFilter = (e) => {
if (e.target.checked) {
// adding value
const temp = [...filter.ratings];
temp.push(e.target.value);
setFilter({ ...filter, ratings: temp });
} else {
// removing value
setFilter({
...filter,
ratings: [...filter.ratings.filter((v) => v !== e.target.value)]
});
}
};
最后,当您在 hotelRooms
上使用 .map
时,您可以在映射之前过滤列表。
{hotelRooms
.filter((h) => filter.ratings.includes(h.hotel.starRating))
.map((h) => (
<div key={h.hotel.name}>
stuff
</div>
))
}