[英]custom hook performance issues in react
I have re-written this javascript code logic to a react custom hook to use.我已将此 javascript 代码逻辑重写为要使用的反应自定义挂钩。
But it seems like the solution i have made is a bit slow, and heavy on performance, I was wondering in which sort of ways I could make it more performant.但似乎我所做的解决方案有点慢,而且性能很重,我想知道我可以通过哪种方式使其性能更高。
This is the custom hook:这是自定义钩子:
import { useEffect, useState } from 'react';
import { isBrowser } from '@utils/environment';
import { NAVBAR_HEIGHT_PX } from '@common/helpers';
export const useSticky = stickyElement => {
const [offset, setOffset] = useState(NAVBAR_HEIGHT_PX);
let offsetTop = NAVBAR_HEIGHT_PX;
let currPos = isBrowser ? window.pageYOffset : 0;
let endScroll = isBrowser ? window.innerHeight - stickyElement?.current?.offsetHeight - 500 : 0;
useEffect(() => {
if (!isBrowser) {
return undefined;
}
const positionStickySidebar = () => {
const { innerHeight, scrollY } = window;
endScroll = innerHeight - stickyElement.current.offsetHeight;
if (window.scrollY < currPos) {
if (offsetTop < NAVBAR_HEIGHT_PX * 2) {
offsetTop = offsetTop + currPos - scrollY;
} else if (offsetTop >= NAVBAR_HEIGHT_PX * 2 && offsetTop !== endScroll) {
offsetTop = NAVBAR_HEIGHT_PX * 2;
}
} else {
if (offsetTop > endScroll) {
offsetTop = offsetTop + currPos - scrollY;
} else if (offsetTop < (endScroll) && offsetTop !== endScroll) {
offsetTop = endScroll;
}
}
setOffset(offsetTop);
currPos = window.scrollY;
};
window.addEventListener('resize', positionStickySidebar, {
capture: false,
passive: true,
});
window.addEventListener('scroll', positionStickySidebar, {
capture: false,
passive: true,
});
return () => {
window.removeEventListener('scroll', positionStickySidebar);
window.removeEventListener('resize', positionStickySidebar);
};
}, []);
return offset;
};
This is the usage of it这是它的用法
const divRef = useRef(null);
const offsetTop = useSticky(divRef);
<ContentContainer offsetTop={offsetTop} ref={divRef}>
And this is the styled component:这是样式化的组件:
export const ContentContainer = styled.div`
position: sticky;
top: ${({ offsetTop }) => `${offsetTop}px`};
`;
I would suggest two things:我建议两件事:
endScroll
variable, because it uses offsetHeight
in calculations.对于endScroll
变量尤其重要,因为它在计算中使用offsetHeight
。 Each invocation of offsetHeight
causes reflow process in browser, which impacts performance a lot.每次调用offsetHeight
都会导致浏览器中的回流过程,这对性能影响很大。 So calling it on each render is not something very good, especially in your case where such calculations doesn't affect anything (except on first render).因此,在每次渲染时调用它并不是一件好事,尤其是在这种计算不会影响任何事情的情况下(第一次渲染除外)。 // Instead of this:
export const useSticky = stickyElement => {
// ...
let offsetTop = NAVBAR_HEIGHT_PX;
let currPos = isBrowser ? window.pageYOffset : 0;
let endScroll = isBrowser ? window.innerHeight - stickyElement?.current?.offsetHeight - 500 : 0;
// ...
}
// Do this:
export const useSticky = stickyElement => {
// ...
useEffect(() => {
if (!isBrowser) return undefined;
let offsetTop = NAVBAR_HEIGHT_PX;
let currPos = isBrowser ? window.pageYOffset : 0;
let endScroll = isBrowser ? window.innerHeight - stickyElement?.current?.offsetHeight - 500 : 0;
const positionStickySidebar = () => {
// ...
}
const [offset, setOffset] =...
) if possible.如果可能,摆脱偏移量 state ( const [offset, setOffset] =...
)。 Performance should become much better if you replace如果更换,性能应该会好得多const [offset, setOffset] = useState(NAVBAR_HEIGHT_PX);
// ...
setOffset(offsetTop);
// ...
return offsetTop;
with和
const topOffsetRef = useRef(NAVBAR_HEIGHT_PX);
// ...
stickyElement.current.style.top = offsetTop + 'px';
topOffsetRef.current = offsetTop;
// ...
return topOffsetRef.current;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.