我正在尝试对我的社交网络中的用户个人资料进行即时搜索。似乎可行,但是在输入更改上设置状态(使用挂钩)会导致延迟一个字符。
我研究了一下,发现状态延迟的问题可以通过在setState中使用回调函数来解决。但是,useState不支持。
这是我的输入元素:
<input
type="text"
placeholder="Enter your query"
name="query"
onChange={e => onChange(e)}
/>
这是我的状态和onChange处理程序:
const [filteredData, setFilteredData] = useState({
query: "",
filteredProfiles: profiles
});
const onChange = e => {
setFilteredData({
query: e.target.value,
filteredProfiles: profiles.filter(person =>
person.user.name.includes(e.target.value)
)
});
console.log(e.target.value); // outputs correct value immediately
console.log(filteredData.query); // it's always one character late
console.log(filteredData.filteredProfiles); //works but 1 char late as well
};
答案 0 :(得分:2)
总是迟到一个字符
控制台日志在上一个状态周期内,因此预计它要“延迟一个周期”。记住setState()
is asynchronous。
如果要记录当前更改,请使用useEffect
钩子。
useEffect(() => {
console.log(filteredData.query); // not late
console.log(filteredData.filteredProfiles); // same here!
}, [filteredData]);
效果挂钩将监听当前filteredData
的更改并将其记录下来。
我还建议将useCallback
用于事件处理程序。
有关完整代码,请参见Code Sandbox。
答案 1 :(得分:0)
您是否尝试过将函数传递给onChange处理程序而不是执行它?像这样的东西:
<input
type="text"
placeholder="Enter your query"
name="query"
onChange={onChange} // Here
/>
这样,您不会在每次渲染组件时都生成新函数,希望对您有所帮助。
答案 2 :(得分:0)
您是要在API中搜索此数据还是在搜索本地数据?关闭代码,似乎您正在搜索本地数据。
每次更改输入时,您都可以使用useEffect
来搜索数据。这样,当前状态将用于查询。
它不起作用的原因是因为您试图设置状态并在相同的“动作”中使用该状态,这将不起作用。状态是“后面有1个字符”,因为它没有机会来更新自己的新结果。.useEffect
可以帮助您。
此外,在这种情况下,您没有要使用 onChange={e => onChange(e)}
,但这并没有任何伤害...您可以只需 onChange={onChange}
,事件就会自动作为参数传递。
类似的事情应该有所帮助。
//// SCROLL DOWN FOR REACT CODE
const apiData = [
{
userId: 1,
id: 1,
title: "delectus aut autem",
completed: false
},
{
userId: 1,
id: 2,
title: "quis ut nam facilis et officia qui",
completed: false
},
{
userId: 1,
id: 3,
title: "fugiat veniam minus",
completed: false
},
{
userId: 1,
id: 4,
title: "et porro tempora",
completed: true
},
{
userId: 1,
id: 5,
title: "laboriosam mollitia et enim quasi adipisci quia provident illum",
completed: false
},
{
userId: 1,
id: 6,
title: "qui ullam ratione quibusdam voluptatem quia omnis",
completed: false
},
{
userId: 1,
id: 7,
title: "illo expedita consequatur quia in",
completed: false
},
{
userId: 1,
id: 8,
title: "quo adipisci enim quam ut ab",
completed: true
}
];
function Searcher() {
const [search, setSearch] = React.useState("et");
const [results, setResults] = React.useState([]);
React.useEffect(() => {
let searchResults;
if (search) {
searchResults = apiData.filter(i => i.title.includes(search));
}
setResults(searchResults);
}, [search]);
const handleInput = e => {
setSearch(e.target.value);
};
return (
<div>
<h4>Search Me!</h4>
{/* You dont have to use "e=>handleInput(e)" in this scenario, but it
doesn't hurt anything... */}
<input type="text" value={search} onChange={e=>handleInput(e)} />
<p>{search}</p>
{search && results && results.length === 0 ? (
<p>No results found!</p>
) : (
<pre>{JSON.stringify(results, null, 2)}</pre>
)}
</div>
);
}
ReactDOM.render(<Searcher />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>