抱歉问了这么长的问题,但我需要做一个介绍以使其更清楚。
我需要一些代码来在我的 Headers 组件<HeaderDesktop>和<MobileHeader>.
起初,我使用 CSS 媒体查询在它们之间切换,使用display: block | none;. 这不太理想,因为这两个组件将同时呈现,这是低效的,并且可能会给隐藏元素上的广告显示带来问题。
SO 上的某个人建议我可以使用window.innerWidthReact 来确定基于此渲染哪个组件。那确实好多了。现在一次只渲染 1 个组件。这就是我所做的:
// INSIDE HEADER COMPONENT
return(
<HeaderWrapper>
{window.innerWidth < 1200 ?
<HeaderMobile/>
: <HeaderDesktop/>
}
</HeaderWrapper>
);
但我需要一种处理调整大小事件的方法。所以我做了:
// INSIDE HEADER COMPONENT
const [windowSize, setWindowSize] = useState(window.innerWidth);
function handleResize() {
setWindowSize(window.innerWidth);
}
return(
<HeaderWrapper>
{windowSize < 1200 ?
<HeaderMobile/>
: <HeaderDesktop/>
}
</HeaderWrapper>
);
好的!那行得通,但现在我的组件在每次调整大小时每秒渲染 1 万亿次。这对性能没有好处。
所以我完成了我的研究并发现了lodash throttle和debounce方法。两者都可以减少和控制处理的事件数量,即使随后触发了数百个事件也是如此。
https://css-tricks.com/debouncing-throttling-explained-examples/
但是我不喜欢将整个库加入我的依赖项列表只是为了使用这样的简单功能,所以我最终创建了以下效果钩子来模仿throttle我的resize事件处理程序的功能。
// INSIDE HEADER COMPONENT
// Ref to store if there's a resize in progress
const resizeInProgress = useRef(false);
// State to store window size
const [windowSize, setWindowSize] = useState(window.innerWidth);
useEffect(() => {
// This function trigger the resize event handler
// And updates the ref saying that there's a resize in progress
// If theres a resize in progress, it doesn't do anything
function handleResize() {
if (resizeInProgress.current === true) {
return;
}
resizeInProgress.current = true;
throttled_updateWindowSize();
}
// This function sets a timeout to update the state with the
// new window size and when it executes, it resets the
// resizeInProgress ref to false. You can execute what's the interval
// You want to handle your resize events, in this case is 1000ms
function throttled_updateWindowSize() {
setTimeout(() => {
console.log("I will be updated!");
console.log(window.innerWidth);
setWindowSize(window.innerWidth);
resizeInProgress.current = false;
}, 1000);
}
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);
您可以在以下沙箱中看到这一点:
https://codesandbox.io/s/v3o0nmvvl0
问题 1
您能否就如何改进调整大小事件处理程序的节流版本的代码给我任何建议?
问题2
我猜我会在其他组件中需要该功能。我怎样才能使它易于重复使用?我可以把它做成一个定制的 Hook 吗?我从未创建过一个,所以我仍然在如何推理它们以及创建它们的正确方法方面遇到一些麻烦。你能帮我把它放到自定义钩子里吗?
还是为此创建一个高阶组件会更好?
