更改输入的状态会延迟一个字符(useState 挂钩)
Posted
技术标签:
【中文标题】更改输入的状态会延迟一个字符(useState 挂钩)【英文标题】:Changing state for input is delayed by one character (useState hook) 【发布时间】:2019-12-15 15:16:48 【问题描述】:我正在尝试在我的社交网络中实现对用户个人资料的即时搜索。它似乎正在工作,但是在输入更改时设置状态(使用挂钩)会导致延迟一个字符。
我研究了一下,发现这个状态延迟问题可以通过在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
;
【问题讨论】:
不是迟到一个字符,是为这次渲染准备的值,下一个值是为下一次渲染准备的 【参考方案1】:您是否尝试过将您的函数传递给 onChange 处理程序而不是执行它?像这样:
<input
type="text"
placeholder="Enter your query"
name="query"
onChange=onChange // Here
/>
这样您就不会在每次渲染组件时都生成新函数,希望对您有所帮助。
【讨论】:
【参考方案2】:您是在搜索此数据的 API,还是在搜索本地数据?关闭您的代码,您似乎正在搜索本地数据..
每次输入更改时,您都可以使用useEffect
搜索您的数据。这样,当前状态将用于您的查询。
它不起作用的原因是因为您试图设置状态并在同一“动作”中使用该状态,这将不起作用。状态是“落后 1 个字符”,因为它没有机会用新的结果更新自己。这就是useEffect
的帮助。
另外,你没有有使用 onChange=e => onChange(e)
在这种情况下,但它不会伤害任何东西......你可以这样做 onChange=onChange
事件会自动作为参数传递。
这样的事情应该会有所帮助..
[CodePen Mirror]
//// 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>
【讨论】:
【参考方案3】:总是迟到一个字符
控制台日志位于前一个状态周期内,因此预计会晚“一个周期”。记住setState()
is asynchronous。
如果要记录当前更改,请使用useEffect
挂钩。
useEffect(() =>
console.log(filteredData.query); // not late
console.log(filteredData.filteredProfiles); // same here!
, [filteredData]);
效果挂钩将侦听当前的filteredData
更改并记录它。
我还建议将useCallback
用于事件处理程序。
【讨论】:
值得补充的是,state中的那个值是当前渲染的,nextValue是下一次渲染的,如果要在当前渲染中使用nextValue,则需要useEffect以上是关于更改输入的状态会延迟一个字符(useState 挂钩)的主要内容,如果未能解决你的问题,请参考以下文章
通过延迟一个字符的相同值更新文本输入状态和AJAX搜索[重复]