React.js 中的功能组件内部去抖
Debounce inside functional component in React.js
尝试在具有随变化更新的输入字段的 React 组件上创建延迟。
代码如下:
import React from 'react';
import Input from "@material-ui/core/Input";
import {debounce} from "lodash";
...
const SampleRow = () => {
let [newFriend, setNewFriend] = React.useState({name: '', lastSeen: '', contactIn: ''});
const onAddFriend = debounce(() => {
if(newFriend.name.length === 0){
return;
}
console.log(newFriend.name);
}, 2000);
return (
<TableRow>
<TableCell component="th" scope="row">
<Input
value={newFriend.name}
onChange={(event) => {
setNewFriend({...newFriend, name: event.target.value});
onAddFriend();
}}
placeholder={"Add friend"}
disableUnderline={true}
/>
</TableCell>
<TableCell align="left">{newFriend.lastSeen ? newFriend.lastSeen : ''}</TableCell>
<TableCell align="left">{newFriend.contactIn ? newFriend.contactIn : ''}</TableCell>
<TableCell align="left" className={classes.externalLinks}/>
</TableRow>
)
};
发生的事情是 console.log
打印出每个更改(在 2 秒超时后),并且不会取消之前的触发器。
问题是为什么会这样?以及如何解决这个问题?
I've found similar questions with complex useDebounce
logic or class-components. Didn't find a reference for this problem.
再见,尝试取消之前的触发:
import React from 'react';
import Input from "@material-ui/core/Input";
import {debounce} from "lodash";
...
const SampleRow = () => {
let [newFriend, setNewFriend] = React.useState({name: '', lastSeen: '', contactIn:
''});
const onAddFriend = debounce((abort) => {
if(abort){
return;
}
console.log(newFriend.name);
}, 2000);
return (
<TableRow>
<TableCell component="th" scope="row">
<Input
value={newFriend.name}
onChange={(event) => {
setNewFriend({...newFriend, name: event.target.value});
let abort = false;
if(event.target.value.length === 0){
abort = true;
}
onAddFriend(abort);
}}
placeholder={"Add friend"}
disableUnderline={true}
/>
</TableCell>
<TableCell align="left">{newFriend.lastSeen ? newFriend.lastSeen : ''}</TableCell>
<TableCell align="left">{newFriend.contactIn ? newFriend.contactIn : ''}</TableCell>
<TableCell align="left" className={classes.externalLinks}/>
</TableRow>
)
};
试试这个。它将始终检查队列中现有的 debounced,并取消它发现任何。
参考:
这里的问题是在每次渲染时都会重新创建去抖功能。
解决此问题的一种方法是将其移出功能组件。另一种方法是将您的组件更改为 Class 组件并将去抖功能保存为 属性.
const { useState } = React
const { debounce } = _;
const onAddFriend = debounce(console.log, 2000);
const App = () => {
const [newFriend, setNewFriend] = useState({name: '', lastSeen: '', contactIn: ''});
const handleInput = (event) => {
setNewFriend({...newFriend, name: event.target.value});
onAddFriend(event.target.value);
}
return (
<div className="box">
<form className="form">
<div class="field">
<label for="name-1">Update {newFriend.name}</label>
<div class="control">
<input type="text" name="name-1" value={newFriend.name}
onChange={handleInput} class="input"/>
</div>
</div>
</form>
</div>
)
}
ReactDOM.render(<App />,
document.getElementById("root"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.19/lodash.min.js"></script>
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>
尝试在具有随变化更新的输入字段的 React 组件上创建延迟。
代码如下:
import React from 'react';
import Input from "@material-ui/core/Input";
import {debounce} from "lodash";
...
const SampleRow = () => {
let [newFriend, setNewFriend] = React.useState({name: '', lastSeen: '', contactIn: ''});
const onAddFriend = debounce(() => {
if(newFriend.name.length === 0){
return;
}
console.log(newFriend.name);
}, 2000);
return (
<TableRow>
<TableCell component="th" scope="row">
<Input
value={newFriend.name}
onChange={(event) => {
setNewFriend({...newFriend, name: event.target.value});
onAddFriend();
}}
placeholder={"Add friend"}
disableUnderline={true}
/>
</TableCell>
<TableCell align="left">{newFriend.lastSeen ? newFriend.lastSeen : ''}</TableCell>
<TableCell align="left">{newFriend.contactIn ? newFriend.contactIn : ''}</TableCell>
<TableCell align="left" className={classes.externalLinks}/>
</TableRow>
)
};
发生的事情是 console.log
打印出每个更改(在 2 秒超时后),并且不会取消之前的触发器。
问题是为什么会这样?以及如何解决这个问题?
I've found similar questions with complex
useDebounce
logic or class-components. Didn't find a reference for this problem.
再见,尝试取消之前的触发:
import React from 'react';
import Input from "@material-ui/core/Input";
import {debounce} from "lodash";
...
const SampleRow = () => {
let [newFriend, setNewFriend] = React.useState({name: '', lastSeen: '', contactIn:
''});
const onAddFriend = debounce((abort) => {
if(abort){
return;
}
console.log(newFriend.name);
}, 2000);
return (
<TableRow>
<TableCell component="th" scope="row">
<Input
value={newFriend.name}
onChange={(event) => {
setNewFriend({...newFriend, name: event.target.value});
let abort = false;
if(event.target.value.length === 0){
abort = true;
}
onAddFriend(abort);
}}
placeholder={"Add friend"}
disableUnderline={true}
/>
</TableCell>
<TableCell align="left">{newFriend.lastSeen ? newFriend.lastSeen : ''}</TableCell>
<TableCell align="left">{newFriend.contactIn ? newFriend.contactIn : ''}</TableCell>
<TableCell align="left" className={classes.externalLinks}/>
</TableRow>
)
};
试试这个。它将始终检查队列中现有的 debounced,并取消它发现任何。
参考:
这里的问题是在每次渲染时都会重新创建去抖功能。
解决此问题的一种方法是将其移出功能组件。另一种方法是将您的组件更改为 Class 组件并将去抖功能保存为 属性.
const { useState } = React
const { debounce } = _;
const onAddFriend = debounce(console.log, 2000);
const App = () => {
const [newFriend, setNewFriend] = useState({name: '', lastSeen: '', contactIn: ''});
const handleInput = (event) => {
setNewFriend({...newFriend, name: event.target.value});
onAddFriend(event.target.value);
}
return (
<div className="box">
<form className="form">
<div class="field">
<label for="name-1">Update {newFriend.name}</label>
<div class="control">
<input type="text" name="name-1" value={newFriend.name}
onChange={handleInput} class="input"/>
</div>
</div>
</form>
</div>
)
}
ReactDOM.render(<App />,
document.getElementById("root"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.19/lodash.min.js"></script>
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>