我的 React 前端中有一个搜索输入字段,用户可以在其中输入内容,每当值发生变化时,就会将发布请求发送到与弹性搜索通信的 Web 服务器。问题如下:
结果:React 首先获取“hello”的响应,然后获取“h”的响应。因此 h 的结果会覆盖“hello”的结果,这不是我想要的。
我该如何解决这个问题?
编辑:
useEffect(() => {
doSearch();
}, [query, cbTitle, cbAbstract, cbAuthor, cbInstitution]); // trickered when input (aka query or cb=Checkboxes) changes
doSearch(){
...
axios
// .post(`http://XXX:5000/search`, data, axios_config)
.post(`/search`, data, axios_config)
.then((res) => {
// console.log(res);
// console.log(res.data);
setSearchResponse(res.data);
});
};
}
编辑2:答案中提到的方法
axios
.post(`http://XXX:5000/search`, data, axios_config)
// .post(`/search`, data, axios_config)
.then((res) => {
// console.log(res);
// console.log(res.data);
if (
res.data["query"] === query &&
res.data["location"] === searchLocation
) {
console.log("latest state:");
console.log(query);
setSearchResponse(res.data["result"]);
}
});
};
编辑3:整个组件
import React, { useState, useEffect } from "react";
import Card from "./CardPaper";
import axios from "axios";
let axios_config = {
headers: {
data: { location: "aits" },
dataType: "json",
xhrFields: {
withCredentials: true,
},
crossDomain: true,
contentType: "application/json; charset=utf-8",
},
};
function Search() {
const [query, setQuery] = useState("");
const [cbTitle, setcbTitle] = useState(true);
const [cbAbstract, setcbAbstract] = useState(true);
const [cbAuthor, setcbAuthor] = useState(true);
const [cbInstitution, setcbInstitution] = useState(true);
const [searchLocation, setSearchLocation] = useState("");
const [searchResponse, setSearchResponse] = useState([]);
useEffect(() => {
doSearch();
}, [query, cbTitle, cbAbstract, cbAuthor, cbInstitution]);
const doSearch = () => {
let search_location = "";
if (cbTitle === true) {
search_location += "t";
}
if (cbAuthor === true) {
search_location += "a";
}
if (cbAbstract === true) {
search_location += "s";
}
if (cbInstitution === true) {
search_location += "i";
}
setSearchLocation(search_location);
let data = { query: query, location: search_location };
axios
.post(`http://XXX:5000/search`, data, axios_config)
// .post(`/search`, data, axios_config)
.then((res) => {
if (
res.data["query"] === query &&
res.data["location"] === searchLocation
) {
console.log("latest state:");
console.log(query);
setSearchResponse(res.data["result"]);
}
});
};
return (
<div className="container mx-auto">
<input
className="block mx-auto w-1/2 border-2 border-gray-300 bg-white h-10 px-5 pr-16 rounded-lg mt-8 focus:outline-none"
type="search"
name="search"
placeholder="Search for title, author or phrases in the abstract of a paper"
value={query}
onChange={(e) => setQuery(e.target.value)}
/>
<div className="mx-auto w-1/2">
<div>
<span className="pl-2">found {searchResponse.length} results</span>
</div>
<div>
<label className="ml-3 block md:inline">
<input
type="checkbox"
class="text-gray-600"
defaultChecked={cbTitle}
onChange={() => {
setcbTitle(!cbTitle);
}}
/>
<span className="ml-2 text-gray-700">Title</span>
</label>
<label className="ml-3 block md:inline">
<input
type="checkbox"
class="ext-gray-600"
checked={cbAbstract}
onChange={() => {
setcbAbstract(!cbAbstract);
}}
/>
<span className="ml-2 text-gray-700">Abstract</span>
</label>
<label className="ml-3 block md:inline">
<input
type="checkbox"
class="text-gray-600"
checked={cbAuthor}
onChange={() => {
setcbAuthor(!cbAuthor);
}}
/>
<span className="ml-2 text-gray-700">Author</span>
</label>
<label className="ml-3 block md:inline">
<input
type="checkbox"
class="ext-gray-600"
checked={cbInstitution}
onChange={() => {
setcbInstitution(!cbInstitution);
}}
/>
<span className="ml-2 text-gray-700">Institution</span>
</label>
</div>
</div>
{searchResponse.map(function (item, index) {
return (
<Card
title={item["title"]}
abstract={item["abstract"]}
authors={item["authors"]}
affliatedInstitutions={item["institutions"]}
link={item["url"]}
/>
);
})}
</div>
);
}
export default Search;
一种选择是将最新搜索到的文本存储在客户端,并在更新 DOM 之前将其与响应进行检查。
示例:下面的函数将为您提供一个想法,我将用户输入存储在变量(latestInput)中,并在响应中我带来相同的数据并进行比较。如果两者匹配则进行更新。
function postSearchData()
{
axios
.post(`/search`, data, axios_config)
.then((res) => {
if(res.data.searchText === query)
setSearchResponse(res.data);
});
}
useEffect(() => {
let ignore = false;
async function fetchProduct() {
const response = await fetch('http://myapi/product/' + productId);
const json = await response.json();
if (!ignore) setProduct(json);
}
fetchProduct();
return () => { ignore = true };
}, [产品ID]);
上述方法将解决乱序请求问题。在本地测试过,效果很好。
可以在setSearchResponse中添加索引
试试这个:
useEffect(() => {
ignoreRef = [false]
doSearch()
return () => { ignoreRef[0] = true }
}, [...])
const doSearch = (ignoreRef = [false]) => {
...
axios.post(...)
.then((res) => {
if (ignoreRef[0]) return
// Do whatever you want and change states
})
}