我希望有人可以在这种情况下向我解释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才可使用。
我不想用用户在框中输入的每个字母来重新查询我的用户列表,但是我想使用一个在用户停止键入后将触发的去弹器。
因此我自然会创建一个useEffect,它将监视值搜索,每次搜索更改时,我都会调用_debounceSearch函数。
现在我的问题是我似乎无法摆脱React依赖关系警告,因为我在第一个useEffect依赖关系中缺少_getUsers函数,该依赖关系已由_debounceSearch fn使用,在第二个useEffect中,我我第二个useEffect依赖项中缺少_debounceSearch。
我该如何以“正确”的方式重写这种代码,这样我就不会以React警告缺少依赖项而告终?
谢谢!
答案 0 :(得分:1)
我将设置一个状态变量来保存去抖动的搜索字符串,并有效地用于获取用户。
假设您的组件将查询参数作为道具,它将是这样的:
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效果,因此不会浪费获取的时间。
随后,如果更改了除搜索之外的任何查询参数,则获取效果将立即运行。 更改搜索参数后,反跳操作将继续执行抓取效果。
但是理想情况下,应该在搜索参数<input />
进行反跳。
在提取组件中执行反跳操作的一个小问题是,搜索中的每项更改都将通过反跳操作,即使它是通过在文本框中键入内容以外的其他方式进行的,例如点击预配置搜索的链接。
答案 1 :(得分:0)
有关钩子依赖关系的规则非常简单明了:如果钩子函数使用或引用了组件范围内的任何变量,则应考虑将其添加到依赖关系列表(https://reactjs.org/docs/hooks-faq.html#is-it-safe-to-omit-functions-from-the-list-of-dependencies)中。
使用您的代码,您应该注意以下几点:
1。对于第一个_getUsers
,使用效果:
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])