![](/img/trans.png)
[英]React useContext() performance, useContext inside custom hook
[英]custom hook performance issues in react
我已将此 javascript 代码逻辑重写为要使用的反应自定义挂钩。
但似乎我所做的解决方案有点慢,而且性能很重,我想知道我可以通过哪种方式使其性能更高。
这是自定义钩子:
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;
};
这是它的用法
const divRef = useRef(null);
const offsetTop = useSticky(divRef);
<ContentContainer offsetTop={offsetTop} ref={divRef}>
这是样式化的组件:
export const ContentContainer = styled.div`
position: sticky;
top: ${({ offsetTop }) => `${offsetTop}px`};
`;
我建议两件事:
endScroll
变量尤其重要,因为它在计算中使用offsetHeight
。 每次调用offsetHeight
都会导致浏览器中的回流过程,这对性能影响很大。 因此,在每次渲染时调用它并不是一件好事,尤其是在这种计算不会影响任何事情的情况下(第一次渲染除外)。 // 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] =...
)。 如果更换,性能应该会好得多const [offset, setOffset] = useState(NAVBAR_HEIGHT_PX);
// ...
setOffset(offsetTop);
// ...
return offsetTop;
和
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.