事件监听器中的状态更新会对挂钩做出反应

问题描述 投票:0回答:1

我创建了简单的自定义挂钩,可以保存屏幕的高度和宽度。问题是我想重新渲染(更新状态)只有当我的状态中的某些条件发生而不是每个resize事件时..我首先尝试简单实现:

const useScreenDimensions = () => {
  const [height, setHeight] = useState(window.innerWidth);
  const [width, setWidth] = useState(window.innerHeight);
  const [sizeGroup, setSizeGroup]useState(getSizeGroup(window.innerWidth));

 useEffect(() => {
  const updateDimensions = () => {
   if (getSizeGroup() !== sizeGroup) {
    setSizeGroup(getSizeGroup(width));
    setHeight(window.innerHeight);
    setWidth(window.innerWidth);
  }
};

  window.addEventListener('resize', updateDimensions);
  return () => window.removeEventListener('resize', updateDimensions);
  }, [sizeGroup, width]);

 return { height, width };

}

这种方法的问题是效果每次调用,我希望效果只调用一次而没有依赖项(sizeGroup,width),因为我不希望每次屏幕宽度/大小发生变化时都注册事件组(window.addEventListener)。

所以,我尝试使用UseCallBack这种方法,但是每次状态发生任何变化时,我的'useEffect'函数都会多次调用。

//useState same as before..
const updateDimensions = useCallback(() => {
  if (getSizeGroup(window.innerWidth) !== sizeGroup) {
  setSizeGroup(getSizeGroup(width));
  setHeight(window.innerHeight);
  setWidth(window.innerWidth);
}
}, [sizeGroup, width]);

useEffect(() => {
 window.addEventListener('resize', updateDimensions);
 return () => window.removeEventListener('resize', updateDimensions);
}, [updateDimensions]);

....
return { height, width };

问题是我的目的是什么正确有效的方法?我只想“注册”一次事件,并且只在我的状态变量为真时更新我的​​状态,而不是每次宽度或其他东西都更新时。

我知道当你将空数组设置为'UseEffect'的第二个参数时,它只运行一次但在我的情况下我希望我的事件监听器的寄存器运行一次并且在调整大小时我将仅在某些条件为真时更新状态

非常感谢。

reactjs react-hooks
1个回答
1
投票

使用2个不同的useEffect

第一个用于注册事件。所以下面的代码将在componentDidMount时运行。

useEffect(() => {
  window.addEventListener('resize', updateDimensions);
}, []);

第二个useEffect基于状态变化运行。

useEffect(() => {
   updateDimensions();
   return () => window.removeEventListener('resize', updateDimensions);
}, [sizeGroup, width])


const updateDimensions = useCallback(() => {
 setSizeGroup(getSizeGroup(width));
 setHeight(window.innerHeight);
 setWidth(window.innerWidth);     
}

我不确定useCallback函数是否需要使用。我还没有测试过这段代码。

© www.soinside.com 2019 - 2024. All rights reserved.