gpt4 book ai didi

javascript - 节流函数(受 lodash 启发)仅使用 React Hook (使用 Sandbox)来处理调整大小事件

转载 作者:行者123 更新时间:2023-11-30 11:05:09 28 4
gpt4 key购买 nike

很抱歉问了这么长的问题,但我需要做一个介绍以使其更清楚。

我需要一些代码来在我的 Headers 组件之间切换 <HeaderDesktop><MobileHeader> .

起初我使用 CSS 媒体查询通过 display: block | none; 在它们之间切换.这不太理想,因为两个组件将同时呈现,这是低效的,并且可能会给隐藏元素上的广告显示带来问题。

SO 上有人建议我可以使用 window.innerWidth并基于此使用 React 确定要渲染的组件。那确实好多了。现在一次只渲染 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 throttledebounce方法。两者都可以减少和控制处理的事件数量,即使随后触发了数百个事件。

https://css-tricks.com/debouncing-throttling-explained-examples/

但我不喜欢将整个库添加到我的依赖项列表中只是为了使用这样一个简单的功能,所以我最终创建了以下效果 Hook 来模仿 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

enter image description here

问题 1

关于如何改进调整大小事件处理程序的节流版本的代码,您能给我一些建议吗?

问题 2

我猜我会在其他组件中需要该功能。我怎样才能使它易于重用?我可以将其设为自定义 Hook 吗?我从来没有创建过一个,所以我仍然在如何推理它们以及创建它们的正确方法方面遇到一些麻烦。你能帮我把它放到 Custom Hook 中吗?

或者为此创建一个高阶组件会更好吗?

最佳答案

这不是我用钩子(Hook)做的事情。您可以让它作为一个 Hook 工作,但您将自己限制在仅在组件内部进行节流,而节流是一个比这更有用的实用功能,而 Hook 不会让它变得更容易或让您做任何额外的事情。

如果您不想导入所有的 lodash,这是可以理解的,但您可以自己实现类似的东西。 Lodash 的 throttle 是一个高阶函数:你将它传递给一个函数,它会返回一个新函数,它只会在自上次执行以来经过了适当的时间后才执行。可以像这样复制执行此操作的代码(没有像 lodash 那样多的选项和安全检查):

const throttle = (func, delay) => {
let inProgress = false;
return (...args) => {
if (inProgress) {
return;
}
inProgress = true;
setTimeout(() => {
func(...args); // Consider moving this line before the set timeout if you want the very first one to be immediate
inProgress = false;
}, delay);
}
}

像这样使用:

useEffect(() => {
const handleResize = throttle(() => {
setWindowSize(window.innerWidth);
}, 1000);

window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);

关于javascript - 节流函数(受 lodash 启发)仅使用 React Hook (使用 Sandbox)来处理调整大小事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55973826/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com