ReactJS 如何在状态具有特定值时运行 API 调用



我正在自学 React,我的一个练习是使用axios从 API 获取国家/地区列表

const fetchCountries = () => {
axios.get("https://restcountries.eu/rest/v2/all").then(response => {
setCountries(response.data);
});
};
React.useEffect(fetchCountries, []);

然后,当用户键入输入时,国家/地区列表会向下过滤。

const handleInputChange = event => {
const filter = event.target.value; // current input value
let matchingCountries = query !== ''
? countries.filter(country => country.name.toLowerCase().indexOf(query.toLowerCase()) !== -1)
: countries;
setQuery(filter);
setMatches(matchingCountries)
console.log('matches', matches)
console.log('query', query)
};

的目标是,当一个国家匹配时,会触发一个新的 API 请求(获取天气,但这不是我的问题,时间是(。匹配单个国家/地区后,我将渲染有关该国家/地区的一些数据,然后获取并渲染单个国家/地区首都的天气详细信息。

我遇到的问题之一是,当我设置状态时,值似乎总是落后一步。例如,在此代码笔中,当您输入 FRA 时,您应该得到"法国"。但是,我必须输入"FRAN"才能获得匹配。当我不使用状态变量进行匹配时(只是let matches年(,这不会发生。这成为一个问题,因为我需要在匹配数 = 1 时运行下一个 API 调用,但匹配状态的长度总是错误的。

所以我想知道 1.如何获得匹配国家的正确状态。和 2.什么时候我应该运行第二个 API 调用,而不会进入无限循环。

使用关注点分离的useEffect解决方案

1个函数应该做 1 件事

  • handleInputChange更新状态
  • useEffect更新状态

但它们不是耦合的。
稍后你可能会有一个名为handleDropdownChange的新函数,它更新状态
在这种情况下,你不需要修改 useEffect

归根结底,我们(开发人员(不喜欢重写东西

const [countries, setCountries] = React.useState([]);
const [query, setQuery] = React.useState("");
const [matches, setMatches] = React.useState([]);

React.useEffect(() => {
let matchingCountries = query !== ''
? countries.filter(country => country.name.toLowerCase().indexOf(query.toLowerCase()) !== -1)
: countries;

setMatches(matchingCountries)
}, [query]);                          // called whenever state.query updated

const handleInputChange = event => {
setQuery(event.target.value);       // update state
};
const fetchCountries = () => {
axios.get("https://restcountries.eu/rest/v2/all").then(response => {
setCountries(response.data);
});
};
React.useEffect(fetchCountries, []);

并且还有直接使用@Joseph D提供的event.target.value的解决方案(不推荐(。

唯一的问题是您在handleInputChange()中使用旧的query值。

请记住,设置状态是异步的(即不会立即生效(

这是一个更新的版本:

const handleInputChange = event => {
const filter = event.target.value; // current input value
let matchingCountries = filter ? <code here>
// ...
setQuery(filter);
};

更新:

如果有一个国家/地区匹配,则调用天气 api 是将matches作为useEffect()中的依赖项。

useEffect(
() => {
async function queryWeatherApi() {
// const data = await fetch(...)
// setData(data)
}
if (matches.length === 1) {
queryWeatherApi();
}
},
[matches]
) 

1( 问题的原因在以下行:

let matchingCountries = filter !== ''
? countries.filter(country => country.name.toLowerCase().indexOf(query.toLowerCase()) !== -1)
: countries;

使用query而不是filter变量,您的处理程序函数应如下所示:

const handleInputChange = event => {
const filter = event.target.value; // current input value
let matchingCountries = filter !== ''
? countries.filter(country => country.name.toLowerCase().indexOf(filter.toLowerCase()) !== -1)
: countries;
setQuery(filter);
setMatches(matchingCountries)
};

2( 在哪里运行下一个 API 调用: 出于学习目的,我不想建议您使用一些应用程序状态管理库,例如redux。只是在setFiltersetQuery之后立即调用它.它将按预期运行。因为调用 API 也是异步的,所以它将在setQuery后执行,并setFilterconsole.log同步函数不会发生的事情。

相关内容

  • 没有找到相关文章

最新更新