如何取消绑定到状态值的输入



我正在尝试取消对输入的抖动。我已经对去抖动处理程序进行了记忆,这样它就不会在每次渲染时更改引用。我需要将输入绑定到状态值,因为我需要在应用程序的其他地方设置它。问题是,输入值永远无法更新,因为在反跳changeHandler e.target.value中时,它总是包含以前的值,而不是新输入的值。如何取消绑定到状态值的输入?

xport function App() {
const [query, setQuery] = useState("a value");
const changeHandler = (event) => {
console.log(event.target.value); // wrong value
setQuery(event.target.value);
};
const debouncedChangeHandler = useCallback(debounce(changeHandler, 1000), []);
return (
<div>
<input
value={query}
onChange={debouncedChangeHandler}
type="text"
placeholder="Type a query..."
/>
</div>
);
}

沙箱:https://codesandbox.io/s/react-debounce-5pidiy?file=/src/index.js:130-596

我不会试图取消键盘输入本身的抖动,我只会等待验证,直到值有一段时间没有改变,然后直接验证它:

const { useState, useEffect, useCallback } = React;
function App() {
const [query, setQuery] = useState("a value");
const changeHandler = (event) => {
setQuery(event.target.value);
};
const validate = useCallback((query) => {
console.log(`Validating "${query}"...`);
});
useEffect(() => {
const timer = setTimeout(() => {
validate(query)
}, 1000);
return () => {
clearTimeout(timer);
}
}, [query]);
return (
<div>
<input
value={query}
onChange={changeHandler}
type="text"
placeholder="Type a query..."
/>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

或者使用单独的状态成员:

const { useState, useEffect, useCallback } = React;
function App() {
const [rawQuery, setRawQuery] = useState("a valid value");
const [query, setQuery] = useState(rawQuery);
const changeHandler = (event) => {
console.log(`raw query: ${event.target.value}`);
setRawQuery(event.target.value);
};
const validate = useCallback((query) => {
console.log(`Validating "${query}"...`);
return query.includes("valid");
});
useEffect(() => {
const timer = setTimeout(() => {
console.log(`validate:  ${rawQuery}`);
if (validate(rawQuery)) {
console.log("Valid!");
setQuery(rawQuery);
} else {
console.log("Invalid!");
setRawQuery(query);
}
}, 1000);
return () => {
clearTimeout(timer);
}
}, [rawQuery, query]);
return (
<div>
<input
value={rawQuery}
onChange={changeHandler}
type="text"
placeholder="Type a query..."
/>
<div>Value to validate: {query}</div>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

这样可以更容易地执行您在注释中所说的内容,如果提供了无效值,则将输入恢复到以前的有效值。

(该更新可以封装在钩子中以供重用。(

最新更新