我正在尝试创建一个输入字段,该字段的值已去抖动(以避免不必要的服务器行程)。第一次渲染我的组件时,我从服务器获取它的值(有一个加载状态等等)。
这是我所拥有的(出于示例的目的,我省略了不相关的代码)。
这是我的去抖钩:
export function useDebounce(value, delay) {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => clearTimeout(handler);
}, [value, delay]);
return debouncedValue;
}
(我从:https : //usehooks.com/useDebounce/得到这个)
是的,这是我的组件以及我如何使用useDebounce
钩子:
function ExampleTitleInput(props) {
const [title, setTitle] = useState(props.title || "");
const [lastCommittedTitle, setLastCommittedTitle] = useState(title);
const [commitsCount, setCommitsCount] = useState(0);
const debouncedTitle = useDebounce(title, 1000);
useEffect(() => {
setTitle(props.title || "");
}, [props.title]);
useEffect(() => {
if (debouncedTitle !== lastCommittedTitle) {
setLastCommittedTitle(debouncedTitle);
setCommitsCount(commitsCount + 1);
}
}, [debouncedTitle, lastCommittedTitle, commitsCount]);
return (
<div className="example-input-container">
<input
type="text"
value={title}
onChange={e => setTitle(e.target.value)}
/>
<div>Last Committed Value: {lastCommittedTitle}</div>
<div>Commits: {commitsCount}</div>
</div>
);
}
这是父组件:
function App() {
const [title, setTitle] = useState("");
useEffect(() => {
setTimeout(() => setTitle("This came async from the server"), 2000);
}, []);
return (
<div className="App">
<h1>Example</h1>
<ExampleTitleInput title={title} />
</div>
);
}
当我运行此代码时,我希望它第一次(仅)忽略 debounce 值更改,因此它应该显示提交次数为 0,因为该值是从 props 传递的。应跟踪任何其他更改。对不起,我度过了漫长的一天,在这一点上我有点困惑(我认为这个“问题”已经很久了)。
我创建了一个示例:
https://codesandbox.io/s/zen-dust-mih5d
它应该显示提交次数为 0 并且正确设置的值没有去抖动更改。
我希望我说得有道理,如果我能提供更多信息,请告诉我。
编辑
这完全符合我的预期,但是它给了我“警告”(注意 deps 数组中缺少依赖项):
function ExampleTitleInput(props) {
const [title, setTitle] = useState(props.title || "");
const [lastCommittedTitle, setLastCommittedTitle] = useState(title);
const [commitsCount, setCommitsCount] = useState(0);
const debouncedTitle = useDebounce(title, 1000);
useEffect(() => {
setTitle(props.title || "");
// I added this line here
setLastCommittedTitle(props.title || "");
}, [props]);
useEffect(() => {
if (debouncedTitle !== lastCommittedTitle) {
setLastCommittedTitle(debouncedTitle);
setCommitsCount(commitsCount + 1);
}
}, [debouncedTitle]); // removed the rest of the dependencies here, but now eslint is complaining and giving me a warning that I use dependencies that are not listed in the deps array
return (
<div className="example-input-container">
<input
type="text"
value={title}
onChange={e => setTitle(e.target.value)}
/>
<div>Last Committed Value: {lastCommittedTitle}</div>
<div>Commits: {commitsCount}</div>
</div>
);
}
这是:https : //codesandbox.io/s/optimistic-perlman-w8uug
这有效,但我担心警告,感觉好像我做错了什么。