我制作了一个搜索栏,允许用户搜索一个特定城市(如果未定义运动)或特定城市中的特定运动(如果定义了运动)中的所有可用运动。 城市将永远被定义。
我在搜索栏上放置了 2 个输入(城市和运动),我希望立即得到结果(以便向我的 API 发出请求,而没有任何触发请求的“搜索”按钮)。
因此,当用户在城市输入上输入内容时,它会触发对 API 的请求,当他在运动输入上输入内容时,它会重新触发请求,但这次是定义了城市和运动。 两个输入值都存储在州(城市和体育)中。
我设法做一些似乎有效的事情,唯一的问题是,如果我在输入搜索中输入一项运动,它不会更新我对 API 的请求。我必须再次在我的输入中重新输入运动,以便更新请求。 我不知道为什么我第一次在运动输入中输入内容时它不更新,因为我在 useEffect 数组中指定了当运动状态改变时它必须重新渲染。
有人能帮我理解吗?
我的代码:
import React, { useState, useEffect } from "react";
import style from "../styles/pdrs.module.css";
import axios from "axios";
import SearchBar from "../components/SearchBar";
const Pdrs = ({ setSearchCity, searchSport, setSearchSport }) => {
// if request's result is loading
const [isLoading, setIsLoading] = useState(false);
// search result
const [searchresults, setSearchresults] = useState(
"Lancez une recherche avec au moins une ville !"
);
// state for the searchbar request
const [city, setCity] = useState("");
const [sport, setSport] = useState(0);
// get city's id for API's request
const fetchCity = async () => {
setIsLoading(true);
try {
// city search
const cityResponse = await axios.get(
`${baseAPI}/city/name=${searchCity}`
);
const city = cityResponse.data;
setCity(city);
setIsLoading(false);
} catch (error) {
console.log(error.message);
setIsLoading(false);
}
};
//fetching sport id
const fetchSport = async () => {
setIsLoading(true);
try {
const sportResponse = await axios.get(
`${baseAPI}/activity/name=${searchSport}`
);
setSport(sportResponse.data.data[0].macro_activity_id);
setIsLoading(false);
} catch (error) {
console.log(error.message);
}
};
//fetching final request response
const fetchDataRequest = async () => {
try {
setIsLoading(true);
const results = await axios.get(
`${baseAPI}/pdrs?city_id=${city.id}${
sport ? "¯o_activity_id=" + sport : ""
}`
);
// manage search results
if (results.data.nb_results === 1) {
setSearchresults({
data: [results.data.data],
nb_results: 1,
});
setNbResults(1);
setIsLoading(false);
} else {
setSearchresults(results.data);
setNbResults(results.data.nb_results);
setIsLoading(false);
}
} catch (error) {
console.log(error.message);
setSearchresults(
"Sorry, nothing was found... !"
);
}
};
useEffect(() => {
if (searchCity) {
fetchCity();
}
if (searchSport) {
fetchSport();
}
}, [searchCity, searchSport]);
useEffect(() => {
if (searchCity) {
fetchDataRequest();
}
}, [searchCity, searchSport]);
console.log(searchresults);
return <>
<main className={`container ${style.pdrs}`}>
<section className={style.searchbar}>
<SearchBar
searchCity={searchCity}
setSearchCity={setSearchCity}
searchSport={searchSport}
setSearchSport={setSearchSport}
searchInstallation={searchInstallation}
setSearchInstallation={setSearchInstallation}
searchType={searchType}
setSearchType={setSearchType}
setPage={setPage}
/>
</section>
<section className={style.results}>
{isLoading ? (
<div>Loading...</div>
) : typeof searchresults === "string" ? (
<div className={`${style.container} ${style.noResults}`}>
<h2>{searchresults}</h2>
</div>
) : (
<>
<div className={style.container}>
<div className={style.resultsList}>
{searchresults.data.map((pdrs) => {
return (
// some code displaying the result
);
})}
</div>
</div>
</>
)}
</section>
</main>
</>;
};
export default Pdrs;
答案 0 :(得分:1)
由于您有两个 useEffect
并且一个正在设置 city
和 sport
,因此您需要进行 debounce 以自行调用获取列表。
我建议您首先更改 API 调用 fetchDataRequest
的使用效果:
useEffect(() => {
if (searchCity) {
fetchDataRequest();
}
}, [city, sport]);
您将听取来自 BE 的实际数据,而不是您填写的输入。
其次,您可以从这里 https://www.npmjs.com/package/use-debounce 使用库 useDebounce
并使用 useDebounceCallback
在您选择运动/城市后延迟调用 API 调用。