Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何为我的应用程序中需要它的所有React组件提供窗口宽度?_Javascript_Reactjs_Responsive Design_React Hooks - Fatal编程技术网

Javascript 如何为我的应用程序中需要它的所有React组件提供窗口宽度?

Javascript 如何为我的应用程序中需要它的所有React组件提供窗口宽度?,javascript,reactjs,responsive-design,react-hooks,Javascript,Reactjs,Responsive Design,React Hooks,所以我有了这个钩子来返回我的应用程序组件的windowWidth。我将此称为选项#1 import {useEffect, useState} from 'react'; function useWindowWidth() { const [windowWidth,setWindowWidth] = useState(window.innerWidth); useEffect(() => { function handleResize() { setWi

所以我有了这个钩子来返回我的应用程序组件的
windowWidth
。我将此称为选项#1

import {useEffect, useState} from 'react';

function useWindowWidth() {

  const [windowWidth,setWindowWidth] = useState(window.innerWidth);

  useEffect(() => {

    function handleResize() {
      setWindowWidth(window.innerWidth);
    }

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

  return windowWidth;
}

export default useWindowWidth;
现在我基本上在每个组件上使用它,这些组件取决于要渲染的窗口宽度,比如:

function Component(props) {
  const windowWidth = useWindowWidth();
  return(
    // RETURN SOMETHING BASED ON WINDOW WIDTH
  );
}
而且,由于钩子有一个事件监听器,用于
调整大小
事件,因此即使在窗口调整大小之后,组件也会保持响应

但我担心,我正在为每个使用该钩子的组件附加一个新的侦听器,这可能会在某个时候减慢速度。我想到了另一种方法:

选项2

我只在像
这样的顶级组件中使用了
useWindowWidth()
钩子一次,我将通过上下文提供整个链的
windowWidth

比如:

问题


我正在用选项1设置多个
resize
侦听器这一事实困扰我,对吗?选项#2是优化该流的好方法吗?

如果您的窗口被您提到的许多组件使用,您必须更喜欢使用
上下文。内容如下:

上下文用于全局应用范围

因此,
#2
是每个反应器的完美选择


第一种方法
#1
可能适用于相同层次结构中的组件,但最多只能达到2-3个级别

我不确定添加和删除事件侦听器是否比设置和删除映射键成本更高,但可能以下操作会对其进行优化:

const changeTracker = (debounceTime => {
  const listeners = new Map();
  const add = fn => {
    listeners.set(fn, fn);
    return () => listeners.delete(fn);
  };
  let debounceTimeout;
  window.addEventListener('resize', () => {
    clearTimeout(debounceTimeout);
    debounceTimeout = setTimeout(
      () => {
        const width=window.innerWidth;
        listeners.forEach(l => l(width))
      },
      debounceTime
    );
  });
  return add;
})(200);
function useWindowWidth() {
  const [windowWidth, setWindowWidth] = useState(
    () => window.innerWidth
  );
  useEffect(
    () =>//changeTracker returns a remove function
      changeTracker((width) =>
        setWindowWidth(width)
      ),
    []
  );
  return windowWidth;
}

自定义钩子使用起来非常好,在卸载组件时删除侦听器。在调整大小时,您可能希望解除锁定,以防止触发许多更新。@HMR谢谢!我有一个脱口而出的版本。但是我多次向
窗口
对象添加和删除事件侦听器不是一个问题吗?我不知道,这可能是一个非常便宜的操作,但它有点困扰我,我设置了多个侦听器,而1就足够了。您认为呢?使用上下文或使用诸如redux之类的状态管理器来存储宽度值会有更好的性能,但即使有数百个组件这样做,去抖动也可能是更好的性能提升。您可以将useWindowWidth设置为从单例对象获取其宽度。
function Component() {
  const windowWidth = useContext(WindowWidthContext);
  return(
    // SOMETHING BASED ON WINDOW WIDTH
  );
}
const changeTracker = (debounceTime => {
  const listeners = new Map();
  const add = fn => {
    listeners.set(fn, fn);
    return () => listeners.delete(fn);
  };
  let debounceTimeout;
  window.addEventListener('resize', () => {
    clearTimeout(debounceTimeout);
    debounceTimeout = setTimeout(
      () => {
        const width=window.innerWidth;
        listeners.forEach(l => l(width))
      },
      debounceTime
    );
  });
  return add;
})(200);
function useWindowWidth() {
  const [windowWidth, setWindowWidth] = useState(
    () => window.innerWidth
  );
  useEffect(
    () =>//changeTracker returns a remove function
      changeTracker((width) =>
        setWindowWidth(width)
      ),
    []
  );
  return windowWidth;
}