我正在尝试使用 React Hooks 构建一个搜索组件,主要功能是当我在输入中放入一个单词时,我使用该单词进行 API 调用,它会返回匹配的单词
现在组件看起来像这样
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import './SearchBar.css';
export function SearchBar() {
const [query, setQuery] = useState('');
const [searchResults, setSearchResults] = useState([]);
const handleChange = event => {
setQuery(event.target.value);
console.log(event);
};
useEffect(() => {
const fetchCities = query => {
const uri = 'http://0.0.0.0:8000/v1/autocomplete/';
axios
.get(uri, {
params: {
q: query
}
})
.then(response => {
const data = response.data.filter(name =>
name.toLowercase().includes(query)
);
setSearchResults(data);
console.log('searchResults' + searchResults);
})
.catch(err => {
console.log(err); //I know this is nothign but im running out of time tbh
});
};
fetchCities();
}, [query]);
const handleSubmit = evt => {
/* evt.preventDefault();
alert(apiCall());
reset(); */
};
return (
<form onSubmit={handleChange} className='display'>
<input
type='text'
placeholder='Search'
onChange={event => setQuery(event.target.value)}
/>
<input type='submit' value='Submit' className='resize' />
<ul>
{searchResults.map(item => (
<li>{item}</li>
))}
</ul>
<div></div>
</form>
);
}
现在在页面加载时我收到此错误
xhr.js:166 GET http://0.0.0.0:8000/v1/autocomplete/ 400 (Bad Request)
dispatchXhrRequest @ xhr.js:166
xhrAdapter @ xhr.js:16
dispatchRequest @ dispatchRequest.js:49
Promise.then (async)
当我只想在提交表单时进行 API 调用时。有什么帮助吗?
useEffect
将在组件首次挂载时触发,因此您需要在其中使用if
语句来决定是否要进行 API 调用:
useEffect(() => {
if (query === "") return
const fetchCities = query => {
// ...
}
fetchCities()
}, [query])
但是,如果您只想在提交表单时触发 API 调用,我会简化您的代码:
function SearchBar() {
const [query, setQuery] = useState('')
// ...
const handleSubmit = (event) => {
event.preventDefault()
const uri = '...'
axios.get(uri, { params: { q: query } })
.then(response => {
// ...
setSearchResults(data)
})
.catch(err => { ... })
}
const handleQueryChange = (event) => {
setQuery(event.target.value)
}
return (
<form onSubmit={handleSubmit}>
<input type="text" placeholder="Search" onChange={handleQueryChange} />
<input type="submit" value="Submit" />
{...}
</form>
)
这样,您就不会在每次在search
字段中键入新字符时调用 API 终端节点。当您单击submit
时,它只会被调用一次。
有关示例,请参阅以下CodeSandbox
链接:
- CodeSandbox React 钩子表单示例
我对你的代码示例做了一些更新:
在我看来,主要问题是获取网址没有运行
import ReactDOM from "react-dom";
import React, { useState, useEffect } from "react";
import axios from "axios";
function App() {
const [query, setQuery] = useState("");
const [searchResults, setSearchResults] = useState([]);
const handleChange = event => {
setQuery(event.target.value);
};
useEffect(() => {
const fetchCities = qry => {
const uri = "https://www.mocky.io/v2/5df693273400002900e5a5f3";
axios
.get(uri, {
params: {
q: qry
}
})
.then(response => {
const data = response.data.tags.filter(name =>
name.toLowerCase().includes(qry)
);
setSearchResults(data);
})
.catch(err => {
console.log("error", err); //I know this is nothign but im running out of time tbh
});
};
fetchCities(query);
}, [query]);
const handleSubmit = evt => {
evt.preventDefault();
};
return (
<form method="POST" onSubmit={handleChange} className="display">
<input
type="text"
placeholder="Search"
onChange={event => setQuery(event.target.value)}
/>
<input
type="submit"
onClick={handleSubmit}
value="Submit"
className="resize"
/>
<ul>
{searchResults.map(item => (
<li>{item}</li>
))}
</ul>
<div />
</form>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);