Javascript React hooks-useffect deps-location.hash上的循环依赖
我有一个Javascript React hooks-useffect deps-location.hash上的循环依赖,javascript,reactjs,react-router,react-hooks,use-effect,Javascript,Reactjs,React Router,React Hooks,Use Effect,我有一个useffect,它读取位置。hash并基于一些其他依赖项,将更改hash。它看起来像这样: useEffect(() => { const hashAlreadyPresent = () => { const hashArr = history.location.hash.split('#'); return hashArr.includes(hashId); }; const addToHash = () => {
useffect
,它读取位置。hash
并基于一些其他依赖项,将更改hash。它看起来像这样:
useEffect(() => {
const hashAlreadyPresent = () => {
const hashArr = history.location.hash.split('#');
return hashArr.includes(hashId);
};
const addToHash = () => {
return history.location.hash.concat(`#${hashId}`);
};
const removeFromHash = () => {
const hashArray = history.location.hash.split('#').filter(hashStr => hashStr);
const indexOfHashId = hashArray.indexOf(hashId);
(indexOfHashId !== -1) && hashArray.splice(indexOfHashId, 1);
return hashArray;
};
// if hashId props is present then attach hash in route
hashId && !hashAlreadyPresent() && history.push({
hash: `${hashAlreadyPresent() ? '' : addToHash()}`,
search: history.location.search,
});
return () => {
// remove hashId only, retain any other hash if present
const hashArray = removeFromHash();
hashId && hashAlreadyPresent() && history.replace({
hash: hashArray.join('#'),
search: history.location.search,
});
};
}, [history, hashId, history.location.hash, history.location.search]);
其中历史记录
来自React路由器
逻辑是,一旦组件出现在屏幕上(挂载),它将向URL添加一个哈希,一旦卸载,它将从URL中删除哈希
当然,就useffect而言,它的意思是:如果任何依赖项发生了变化,那么之前的效果将被清除,并且效果的新实例将就位。有效的deps规则在这方面帮助了我,因为之前我忽略了一个事实,即如果hashId
发生变化,应该清理并重新运行这个钩子
现在,我们应该依赖于history.location.hash
来获得详尽的DEP,但问题是每次我从钩子中更改hash
,钩子都会再次运行(前面的实例将再次清理并更改hash
),这将导致无限更新类型的场景
注意:我知道这可以通过关闭deps规则并从依赖项中排除history.location.hash
来实现,但我想找出重构/分解useffect
的任何可能性,以便在不关闭它的情况下解决这个问题
另一件需要注意的事情是,如果我将history
添加为依赖项(我必须这样做,因为我使用的是history
中的方法),那么规则不会要求我显式添加嵌套的依赖项(history.lcoation.search
,history.location.hash
),但是,应该添加它们,由于历史
对象将保持不变,但嵌套对象将随url更改而更改。这与将completeprops
对象指定为依赖项而不是仅指定所需的特定嵌套属性的用例相同
我是否应该在useEffect中设置一个基于位置更改的条件,该条件可以告诉我位置是否从钩子内部更改,因此不做任何事情
我是否应该以不同的方式分解并指定依赖项,以便在效果中更改location.hash时效果不会运行
注意:
在github上对此进行了讨论。有更多的见解。
指定非空依赖项数组时,添加到依赖项数组中的任何值都会首先运行清理函数(第一次渲染时除外),然后运行效果函数(卸载期间除外)。若要确定某个值是否应进入依赖项数组,请尝试回答该值的以下问题: 更新此值时,应再次运行效果,以便:
- 观察到了预期的效果
- 如有必要,将清除之前所做的任何潜在更改
- 没有引入因过时引用而导致的错误
useffect
函数中使用的所有值回答上述问题:
:是。这是效果的主要驱动因素,每次该值更改时,URL都应反映更改。这成为效果的真实来源。因此,这是确保达到预期效果所必需的。此外,清理以前的hashId
也需要这样做,因为清理函数需要引用以前的hashId
hashId
:是。我认为,由于这是由react router提供的,所以在组件的整个生命周期中,引用不应该改变。从这个意义上讲,在这里添加它的唯一目的是满足lint规则,没有实际影响(除了额外的引用检查)。但是,如果它确实发生了更改,effect函数将有一个过时的引用,这可能会导致bug。这件事必须处理好历史记录
:否。这与主要效果无关,因为只需要历史记录.位置.搜索
即可确保观察到所需的效果。也没有过时引用的危险,因为它总是从hashId
对象中读取。由于历史记录
对象是可变的,每次都用最新的值更新,并且已经是依赖项数组的一部分,因此可以安全地省略history
*李>history.location.search
:否,用于与history.location.hash
相同的参数。此外,总是由history.location.search
确定hashId
应该是什么,因此不应使用此值的更新来重新运行效果history.location.hash
[hashId,history]
**
*小心不要从
历史记录中提取搜索
。位置
,并在清理功能中使用搜索
,因为这将是一个过时的引用
**注意到
routeModal
正在效果主体中使用,如果需要,这也必须是依赖项数组的一部分已经删除了routeModal内容,如果让我们说我删除历史记录,这是一个输入错误。推送/历史记录。从useEffect中替换代码,lint规则将开始抱怨history.location.hash
应该是一个依赖项,因此我认为删除history.location.search
不应该满足详尽的deps,尽管在这种情况下它会起作用,就像在中一样,规则不会抱怨,因为父对象历史记录已在Dependencies中指定。但是我们