我希望有人能向我解释在这种情况下React钩子的正确用法,因为我似乎找不到它。
以下是我的代码
useEffect(() => {
_getUsers()
}, [page, perPage, order, type])
// This is a trick so that the debounce doesn't run on initial page load
// we use a ref, and set it to true, then set it to false after
const firstUpdate = React.useRef(true);
const UserSearchTimer = React.useRef()
useEffect(() => {
if(firstUpdate.current)
firstUpdate.current = false;
else
_debounceSearch()
}, [search])
function _debounceSearch() {
clearTimeout(UserSearchTimer.current);
UserSearchTimer.current = setTimeout( async () => {
_getUsers();
}, DEBOUNCE_TIMER);
}
async function _getUsers(query = {}) {
if(type) query.type = type;
if(search) query.search = search;
if(order.orderBy && order.order) {
query.orderBy = order.orderBy;
query.order = order.order;
}
query.page = page+1;
query.perPage = perPage;
setLoading(true);
try {
await get(query);
}
catch(error) {
console.log(error);
props.onError(error);
}
setLoading(false);
}
因此,实际上我有一个表,当页面更改、perPage更改、顺序更改或类型更改时,我会在其中显示用户,因此我希望重新查询用户列表,以便在这种情况下有一个useEffect。
现在,我通常会将_getUsers()函数放入该useEffect中,但唯一的问题是,当我的用户开始在搜索框中进行搜索时,我有另一个useEffect供我使用。
我不想用用户在框中输入的每个字母来重新查询我的用户列表,而是想使用一个在用户停止输入后触发的去保证器。
所以我自然会创建一个useEffect,它会观察值搜索,每次搜索更改时,我都会调用我的_debounceSearch函数。
现在我的问题是,我似乎无法摆脱React dependency警告,因为我的第一个useEffect依赖项中缺少_getUsers函数,我的_debounceSearch fn正在使用它,而在我的第二个useEffect中,我的第二个useEffect依赖项中缺少_debounceSearch。
我怎样才能以“正确”的方式重写它,这样我就不会因为缺少依赖而得到React警告?
提前感谢!
发布于 2019-09-17 11:12:37
我将设置一个状态变量来保存去掉的搜索字符串,并将其用于获取用户。
假设您的组件将查询参数作为props获取,它将如下所示:
function Component({page, perPage, order, type, search}) {
const [debouncedSearch, setDebouncedSearch] = useState(search);
const debounceTimer = useRef(null);
// debounce
useEffect(() => {
if(debounceTime.current) {
clearTimeout(UserSearchTimer.current);
}
debounceTime.current = setTimeout(() => setDebouncedSearch(search), DEBOUNCE_DELAY);
}, [search]);
// fetch
useEffect(() => {
async function _getUsers(query = {}) {
if(type) query.type = type;
if(debouncedSearch) query.search = debouncedSearch;
if(order.orderBy && order.order) {
query.orderBy = order.orderBy;
query.order = order.order;
}
query.page = page+1;
query.perPage = perPage;
setLoading(true);
try {
await get(query);
}
catch(error) {
console.log(error);
props.onError(error);
}
setLoading(false);
}
_getUsers();
}, [page, perPage, order, type, debouncedSearch]);
}
在初始渲染时,去抖动效果将设置一个去抖动计时器...但这是可以的。
在去抖动延迟之后,它会将deboucedSearch
状态设置为相同的值。
由于deboucedSearch没有改变,ferch效果将不会运行,因此不会浪费fetch。
随后,当更改除搜索之外的任何查询参数时,fetch effect将立即运行。当搜索参数改变时,fetch效果将在去抖动后运行。
理想情况下,去抖动应该在搜索参数的<input />
处完成。在抓取组件中进行去抖动的一个小问题是,搜索中的每个变化都会经历去抖动,即使它是通过在文本框中键入以外的方式发生的,例如,点击预先配置的搜索的链接。
发布于 2019-09-17 00:55:55
钩子依赖关系的规则非常简单明了:如果钩子函数使用或引用组件作用域中的任何变量,您应该考虑将其添加到依赖关系列表(https://reactjs.org/docs/hooks-faq.html#is-it-safe-to-omit-functions-from-the-list-of-dependencies)中。
对于你的代码,有几件事你应该知道:
1.使用第一个_getUsers
useEffect:
useEffect(() => {
_getUsers()
}, [page, perPage, order, type])
// Correctly it should be:
useEffect(() => {
_getUsers()
}, [_getUsers])
此外,您的_getUsers
函数当前在组件每次重新呈现时都会重新创建,您可以考虑使用React.useCallback
来对其进行记忆。
2.第二个useEffect
useEffect(() => {
if(firstUpdate.current)
firstUpdate.current = false;
else
_debounceSearch()
}, [search])
// Correctly it should be
useEffect(() => {
if(firstUpdate.current)
firstUpdate.current = false;
else
_debounceSearch()
}, [firstUpdate, _debounceSearch])
https://stackoverflow.com/questions/57965832
复制相似问题