Rerender вид в браузере изменить размер с React

Как я могу заставить React повторно визуализировать представление при изменении размера окна браузера?

Фон

У меня есть несколько блоков, которые я хочу разместить на странице по отдельности, но я также хочу, чтобы они обновлялись при изменении окна браузера. Самым конечным результатом будет что-то вроде макета Pinterest Бена Холланда, но написанное с использованием React, а не только jQuery. Я все еще далеко.

Код

Вот мое приложение:

var MyApp = React.createClass({
  //does the http get from the server
  loadBlocksFromServer: function() {
    $.ajax({
      url: this.props.url,
      dataType: 'json',
      mimeType: 'textPlain',
      success: function(data) {
        this.setState({data: data.events});
      }.bind(this)
    });
  },
  getInitialState: function() {
    return {data: []};
  },
  componentWillMount: function() {
    this.loadBlocksFromServer();

  },    
  render: function() {
    return (
        <div>
      <Blocks data={this.state.data}/>
      </div>
    );
  }
});

React.renderComponent(
  <MyApp url="url_here"/>,
  document.getElementById('view')
)

Тогда у меня есть Block компонент (эквивалентный Pin в приведенном выше примере Pinterest):

var Block = React.createClass({
  render: function() {
    return (
        <div class="dp-block" style={{left: this.props.top, top: this.props.left}}>
        <h2>{this.props.title}</h2>
        <p>{this.props.children}</p>
        </div>
    );
  }
});

и список / коллекция Blocks:

var Blocks = React.createClass({

  render: function() {

    //I've temporarily got code that assigns a random position
    //See inside the function below...

    var blockNodes = this.props.data.map(function (block) {   
      //temporary random position
      var topOffset = Math.random() * $(window).width() + 'px'; 
      var leftOffset = Math.random() * $(window).height() + 'px'; 
      return <Block order={block.id} title={block.summary} left={leftOffset} top={topOffset}>{block.description}</Block>;
    });

    return (
        <div>{blockNodes}</div>
    );
  }
});

Вопрос

Должен ли я добавить изменение размера окна jQuery? Если так, то где?

$( window ).resize(function() {
  // re-render the component
});

Есть ли более "Реактивный" способ сделать это?

25 ответов

Решение

Вы можете слушать в componentDidMount, что-то вроде этого компонента, который просто отображает размеры окна (например, <span>1024 x 768</span>):

var WindowDimensions = React.createClass({
    render: function() {
        return <span>{this.state.width} x {this.state.height}</span>;
    },
    updateDimensions: function() {
        this.setState({width: $(window).width(), height: $(window).height()});
    },
    componentWillMount: function() {
        this.updateDimensions();
    },
    componentDidMount: function() {
        window.addEventListener("resize", this.updateDimensions);
    },
    componentWillUnmount: function() {
        window.removeEventListener("resize", this.updateDimensions);
    }
});

@SophieAlpert прав, +1, я просто хочу предоставить модифицированную версию ее решения без jQuery, основываясь на этом ответе.

var WindowDimensions = React.createClass({
    render: function() {
        return <span>{this.state.width} x {this.state.height}</span>;
    },
    updateDimensions: function() {

    var w = window,
        d = document,
        documentElement = d.documentElement,
        body = d.getElementsByTagName('body')[0],
        width = w.innerWidth || documentElement.clientWidth || body.clientWidth,
        height = w.innerHeight|| documentElement.clientHeight|| body.clientHeight;

        this.setState({width: width, height: height});
        // if you are using ES2015 I'm pretty sure you can do this: this.setState({width, height});
    },
    componentWillMount: function() {
        this.updateDimensions();
    },
    componentDidMount: function() {
        window.addEventListener("resize", this.updateDimensions);
    },
    componentWillUnmount: function() {
        window.removeEventListener("resize", this.updateDimensions);
    }
});

Очень простое решение:

resize = () => this.forceUpdate()

componentDidMount() {
  window.addEventListener('resize', this.resize)
}

componentWillUnmount() {
  window.removeEventListener('resize', this.resize)
}

Это простой и короткий пример использования es6 без jQuery.

import React, { Component } from 'react';

export default class CreateContact extends Component {
  state = {
    windowHeight: undefined,
    windowWidth: undefined
  }

  handleResize = () => this.setState({
    windowHeight: window.innerHeight,
    windowWidth: window.innerWidth
  });

  componentDidMount() {
    this.handleResize();
    window.addEventListener('resize', this.handleResize)
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.handleResize)
  }

  render() {
    return (
      <span>
        {this.state.windowWidth} x {this.state.windowHeight}
      </span>
    );
  }
}

Обновление в 2020 году. Для разработчиков React, серьезно относящихся к производительности.

Вышеупомянутые решения работают, НО будут повторно отображать ваши компоненты всякий раз, когда размер окна изменяется на один пиксель.

Это часто вызывает проблемы с производительностью, поэтому я написал useWindowDimension крючок, который разрушает resizeсобытие на короткий период времени. например, 100 мс

import React, { useState, useEffect } from 'react';

export function useWindowDimension() {
  const [dimension, setDimension] = useState([
    window.innerWidth,
    window.innerHeight,
  ]);
  useEffect(() => {
    const debouncedResizeHandler = debounce(() => {
      console.log('***** debounced resize'); // See the cool difference in console
      setDimension([window.innerWidth, window.innerHeight]);
    }, 100); // 100ms
    window.addEventListener('resize', debouncedResizeHandler);
    return () => window.removeEventListener('resize', debouncedResizeHandler);
  }, []); // Note this empty array. this effect should run only on mount and unmount
  return dimension;
}

function debounce(fn, ms) {
  let timer;
  return _ => {
    clearTimeout(timer);
    timer = setTimeout(_ => {
      timer = null;
      fn.apply(this, arguments);
    }, ms);
  };
}

Используйте это так.

function YourComponent() {
  const [width, height] = useWindowDimension();
  return <>Window width: {width}, Window height: {height}</>;
}

Начиная с React 16.8, вы можете использовать крючки!

/* globals window */
import React, { useState, useEffect } from 'react'
import _debounce from 'lodash.debounce'

const Example = () => {
  const [width, setWidth] = useState(window.innerWidth)

  useEffect(() => {
    const handleResize = _debounce(() => setWidth(window.innerWidth), 100)

    window.addEventListener('resize', handleResize);

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

  return <>Width: {width}</>
}

Edit 2018: теперь React имеет первоклассную поддержку контекста


Я постараюсь дать общий ответ, который нацелен на эту конкретную проблему, но также и на более общую проблему.

Если вам не нужны побочные эффекты, вы можете просто использовать что-то вроде Packery

Если вы используете Flux, вы можете создать хранилище, содержащее свойства окна, чтобы вы сохраняли чистую функцию рендеринга без необходимости каждый раз запрашивать объект окна.

В других случаях, когда вы хотите создать адаптивный веб-сайт, но предпочитаете встроенные стили React медиазапросам или хотите, чтобы поведение HTML/JS изменялось в зависимости от ширины окна, продолжайте читать:

Что такое контекст React и почему я об этом говорю

Реагирующий контекст an не находится в общедоступном API и позволяет передавать свойства всей иерархии компонентов.

Контекст React особенно полезен для передачи всему вашему приложению того, что никогда не меняется (его используют многие фреймворки Flux через миксин). Вы можете использовать его для хранения бизнес-инвариантов приложения (например, подключенного userId, чтобы он был доступен везде).

Но его также можно использовать для хранения вещей, которые могут измениться. Проблема заключается в том, что при изменении контекста все компоненты, которые его используют, должны быть перерисованы, а это нелегко сделать, лучшее решение часто заключается в размонтировании / перемонтировании всего приложения с новым контекстом. Помните, что forceUpdate не является рекурсивным.

Итак, как вы понимаете, контекст практичен, но когда он изменяется, он влияет на производительность, поэтому он не должен меняться слишком часто.

Что поставить в контекст

  • Инварианты: как подключенный userId, sessionToken, что угодно...
  • Вещи, которые не часто меняются

Вот вещи, которые не часто меняются:

Текущий язык пользователя:

Это не очень часто меняется, и когда это происходит, когда переводится все приложение, мы должны перерисовывать все: очень хороший пример использования горячих изменений языка.

Свойства окна

Ширина и высота меняются не часто, но когда мы делаем наш макет и поведение, возможно, придется адаптироваться. Иногда для макета его легко настроить с помощью медиазапросов CSS, но иногда это не так и требует другой структуры HTML. Для поведения вы должны справиться с этим с помощью Javascript.

Вы не хотите перерисовывать все при каждом событии изменения размера, поэтому вы должны отменить события изменения размера.

Что я понимаю в вашей проблеме, так это то, что вы хотите знать, сколько элементов отображается в зависимости от ширины экрана. Таким образом, вы должны сначала определить отзывчивые точки останова и перечислить количество различных типов макетов, которые вы можете иметь.

Например:

  • Макет "1col", для ширины <= 600
  • Макет "2col", для 600 <ширина <1000
  • Макет "3col", для 1000 <= ширина

При изменении размера событий (не обсуждалось) вы можете легко получить текущий тип макета, запросив объект окна.

Затем вы можете сравнить тип макета с прежним типом макета и, если он изменился, повторно выполнить рендеринг приложения с новым контекстом: это позволяет избежать повторного рендеринга приложения вообще, когда пользователь запускает события изменения размера, но на самом деле Тип макета не изменился, поэтому вы можете выполнить повторную визуализацию только при необходимости.

Как только вы это сделаете, вы можете просто использовать тип макета внутри вашего приложения (доступный через контекст), чтобы вы могли настроить HTML, поведение, классы CSS... Вы знаете свой тип макета внутри функции рендеринга React, так что это означает, что вы может безопасно создавать адаптивные веб-сайты, используя встроенные стили, и вообще не нуждается в медиазапросах.

Если вы используете Flux, вы можете использовать хранилище вместо контекста React, но если в вашем приложении много отзывчивых компонентов, может быть, проще использовать контекст?

Я использую решение @senornestor, но чтобы быть полностью правильным, вы должны также удалить прослушиватель событий:

componentDidMount() {
    window.addEventListener('resize', this.handleResize);
}

componentWillUnmount(){
    window.removeEventListener('resize', this.handleResize);
}

handleResize = () => {
    this.forceUpdate();
};

В противном случае вы получите предупреждение:

Предупреждение: forceUpdate(...): может обновлять только смонтированный или монтируемый компонент. Обычно это означает, что вы вызвали forceUpdate() для несмонтированного компонента. Это неоперация. Пожалуйста, проверьте код для компонента XXX.

Хотел поделиться этой довольно классной вещью, которую я только что нашел, используя window.matchMedia

const mq = window.matchMedia('(max-width: 768px)');

  useEffect(() => {
    // initial check to toggle something on or off
    toggle();

    // returns true when window is <= 768px
    mq.addListener(toggle);

    // unmount cleanup handler
    return () => mq.removeListener(toggle);
  }, []);

  // toggle something based on matchMedia event
  const toggle = () => {
    if (mq.matches) {
      // do something here
    } else {
      // do something here
    }
  };

.matches вернет true или false, если окно выше или ниже указанного значения max-width, это означает, что нет необходимости регулировать слушателя, так как matchMedia запускается только один раз, когда изменяется логическое значение.

Мой код можно легко настроить, чтобы включить useState чтобы сохранить логические возвращаемые значения matchMedia и использовать их для условного рендеринга компонента, действия огня и т. д.

Я бы пропустил все приведенные выше ответы и начал бы использовать react-dimensions Компонент высшего порядка.

https://github.com/digidem/react-dimensions

Просто добавьте простой import и вызов функции, и вы можете получить доступ this.props.containerWidth а также this.props.containerHeight в вашем компоненте.

// Example using ES6 syntax
import React from 'react'
import Dimensions from 'react-dimensions'

class MyComponent extends React.Component {
  render() (
    <div
      containerWidth={this.props.containerWidth}
      containerHeight={this.props.containerHeight}
    >
    </div>
  )
}

export default Dimensions()(MyComponent) // Enhanced component

Этот код использует новый API контекста React:

  import React, { PureComponent, createContext } from 'react';

  const { Provider, Consumer } = createContext({ width: 0, height: 0 });

  class WindowProvider extends PureComponent {
    state = this.getDimensions();

    componentDidMount() {
      window.addEventListener('resize', this.updateDimensions);
    }

    componentWillUnmount() {
      window.removeEventListener('resize', this.updateDimensions);
    }

    getDimensions() {
      const w = window;
      const d = document;
      const documentElement = d.documentElement;
      const body = d.getElementsByTagName('body')[0];
      const width = w.innerWidth || documentElement.clientWidth || body.clientWidth;
      const height = w.innerHeight || documentElement.clientHeight || body.clientHeight;

      return { width, height };
    }

    updateDimensions = () => {
      this.setState(this.getDimensions());
    };

    render() {
      const { children } = this.props;

      return <Provider value={this.state}>{children}</Provider>;
    }
  }

  export default WindowProvider;
  export const WindowConsumer = Consumer;

Затем вы можете использовать его где угодно в своем коде, например так:

<WindowConsumer>
  {{(width, height)} => //do what you want}
</WindowConsumer>

Не уверен, что это лучший подход, но для меня сначала было создать Магазин, я назвал его WindowStore:

import {assign, events} from '../../libs';
import Dispatcher from '../dispatcher';
import Constants from '../constants';

let CHANGE_EVENT = 'change';
let defaults = () => {
    return {
        name: 'window',
        width: undefined,
        height: undefined,
        bps: {
            1: 400,
            2: 600,
            3: 800,
            4: 1000,
            5: 1200,
            6: 1400
        }
    };
};
let save = function(object, key, value) {
    // Save within storage
    if(object) {
        object[key] = value;
    }

    // Persist to local storage
    sessionStorage[storage.name] = JSON.stringify(storage);
};
let storage;

let Store = assign({}, events.EventEmitter.prototype, {
    addChangeListener: function(callback) {
        this.on(CHANGE_EVENT, callback);
        window.addEventListener('resize', () => {
            this.updateDimensions();
            this.emitChange();
        });
    },
    emitChange: function() {
        this.emit(CHANGE_EVENT);
    },
    get: function(keys) {
        let value = storage;

        for(let key in keys) {
            value = value[keys[key]];
        }

        return value;
    },
    initialize: function() {
        // Set defaults
        storage = defaults();
        save();
        this.updateDimensions();
    },
    removeChangeListener: function(callback) {
        this.removeListener(CHANGE_EVENT, callback);
        window.removeEventListener('resize', () => {
            this.updateDimensions();
            this.emitChange();
        });
    },
    updateDimensions: function() {
        storage.width =
            window.innerWidth ||
            document.documentElement.clientWidth ||
            document.body.clientWidth;
        storage.height =
            window.innerHeight ||
            document.documentElement.clientHeight ||
            document.body.clientHeight;
        save();
    }
});

export default Store;

Затем я использовал этот магазин в своих компонентах, вроде этого:

import WindowStore from '../stores/window';

let getState = () => {
    return {
        windowWidth: WindowStore.get(['width']),
        windowBps: WindowStore.get(['bps'])
    };
};

export default React.createClass(assign({}, base, {
    getInitialState: function() {
        WindowStore.initialize();

        return getState();
    },
    componentDidMount: function() {
        WindowStore.addChangeListener(this._onChange);
    },
    componentWillUnmount: function() {
        WindowStore.removeChangeListener(this._onChange);
    },
    render: function() {
        if(this.state.windowWidth < this.state.windowBps[2] - 1) {
            // do something
        }

        // return
        return something;
    },
    _onChange: function() {
        this.setState(getState());
    }
}));

К вашему сведению, эти файлы были частично обрезаны.

Вам не обязательно форсировать повторную визуализацию.

Это может не помочь OP, но в моем случае мне нужно было только обновить width а также height атрибуты на моем холсте (что вы не можете сделать с помощью CSS).

Это выглядит так:

import React from 'react';
import styled from 'styled-components';
import {throttle} from 'lodash';

class Canvas extends React.Component {

    componentDidMount() {
        window.addEventListener('resize', this.resize);
        this.resize();
    }

    componentWillUnmount() {
        window.removeEventListener('resize', this.resize);
    }

    resize = throttle(() => {
        this.canvas.width = this.canvas.parentNode.clientWidth;
        this.canvas.height = this.canvas.parentNode.clientHeight;
    },50)

    setRef = node => {
        this.canvas = node;
    }

    render() {
        return <canvas className={this.props.className} ref={this.setRef} />;
    }
}

export default styled(Canvas)`
   cursor: crosshair;
`

На этой кухне много поваров, но я все равно закину шляпу. Я бы сказал, что ни одно из этих применений не является наиболее эффективным.

Вот пример использования хуков React иrequestAnimationFrame. Это также использует чистый js без каких-либо библиотек, таких как lodash (которых я избегаю любой ценой из-за размера пакета).

      import { useState, useEffect, useCallback } from 'react';

const getSize = () => {
  return { 
    width: window.innerWidth,
    height: window.innerHeight,
  };
};
 
export function useResize() {
 
  const [size, setSize] = useState(getSize());
 
  const handleResize = useCallback(() => {
    let ticking = false;
    if (!ticking) {
      window.requestAnimationFrame(() => {
        setSize(getSize());
        ticking = false;
      });
      ticking = true;
    } 
  }, []);

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

Вот суть, показывающая его использование: Img.tsx с useResize . Кроме того, вы можете увидеть это в моем репо здесь для большего контекста.

Некоторые ресурсы о том, почему вы должны сделать это вместо устранения дребезга вашей функции:

Спасибо, что пришли на мой Ted Talk.

Я знаю, что на этот вопрос уже был дан ответ, но подумал, что поделюсь своим решением, так как лучший ответ, хотя и отличный, может теперь немного устареть.

    constructor (props) {
      super(props)

      this.state = { width: '0', height: '0' }

      this.initUpdateWindowDimensions = this.updateWindowDimensions.bind(this)
      this.updateWindowDimensions = debounce(this.updateWindowDimensions.bind(this), 200)
    }

    componentDidMount () {
      this.initUpdateWindowDimensions()
      window.addEventListener('resize', this.updateWindowDimensions)
    }

    componentWillUnmount () {
      window.removeEventListener('resize', this.updateWindowDimensions)
    }

    updateWindowDimensions () {
      this.setState({ width: window.innerWidth, height: window.innerHeight })
    }

Единственное отличие на самом деле в том, что я отменил (запускаю каждые 200 мс) updateWindowDimensions для события resize, чтобы немного повысить производительность, НО не отсекая его, когда он вызывается на ComponentDidMount.

Я обнаружил, что отскок иногда делает его довольно медленным, если вы часто его монтируете.

Просто небольшая оптимизация, но надеюсь, что она кому-нибудь поможет!

componentDidMount() {

    // Handle resize
    window.addEventListener('resize', this.handleResize);
}




handleResize = () => {
    this.renderer.setSize(this.mount.clientWidth, this.mount.clientHeight);
    this.camera.aspect = this.mount.clientWidth / this.mount.clientHeight;
    this.camera.updateProjectionMatrix();
};

Нужно только определить функцию изменения размера события.

Затем обновите размер рендера (холст), назначьте новое соотношение сторон для камеры.

Размонтирование и перенастройка - сумасшедшее решение, на мой взгляд....

ниже крепление при необходимости.

            <div
                className={this.state.canvasActive ? 'canvasContainer isActive' : 'canvasContainer'}
                ref={mount => {
                    this.mount = mount;
                }}
            />

Просто чтобы улучшить решение @senornestor для использования forceUpdate и решение @gkri для удаления resize прослушиватель событий для компонента unmount:

  1. не забудьте ограничить (или отменить) вызов для изменения размера
  2. убедитесь, что bind(this) в конструкторе
import React from 'react'
import { throttle } from 'lodash'

class Foo extends React.Component {
  constructor(props) {
    super(props)
    this.resize = throttle(this.resize.bind(this), 100)
  }

  resize = () => this.forceUpdate()

  componentDidMount() {
    window.addEventListener('resize', this.resize)
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.resize)
  }

  render() {
    return (
      <div>{window.innerWidth} x {window.innerHeight}</div>
    )
  }
}

Другой метод состоит в том, чтобы просто использовать "фиктивное" состояние вместо forceUpdate:

import React from 'react'
import { throttle } from 'lodash'

class Foo extends React.Component {
  constructor(props) {
    super(props)
    this.state = { foo: 1 }
    this.resize = throttle(this.resize.bind(this), 100)
  }

  resize = () => this.setState({ foo: 1 })

  componentDidMount() {
    window.addEventListener('resize', this.resize)
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.resize)
  }

  render() {
    return (
      <div>{window.innerWidth} x {window.innerHeight}</div>
    )
  }
}

Пришлось связать его с этим в конструкторе, чтобы он работал с синтаксисом класса

class MyComponent extends React.Component {
  constructor(props) {
    super(props)
    this.resize = this.resize.bind(this)      
  }
  componentDidMount() {
    window.addEventListener('resize', this.resize)
  }
  componentWillUnmount() {
    window.removeEventListener('resize', this.resize)
  }
}

Спасибо всем за ответы. Вот мой Реакт + Рекомендовать. Это функция высокого порядка, которая включает в себя windowHeight а также windowWidth свойства к компоненту.

const withDimensions = compose(
 withStateHandlers(
 ({
   windowHeight,
   windowWidth
 }) => ({
   windowHeight: window.innerHeight,
   windowWidth: window.innerWidth
 }), {
  handleResize: () => () => ({
    windowHeight: window.innerHeight,
    windowWidth: window.innerWidth
  })
 }),
 lifecycle({
   componentDidMount() {
   window.addEventListener('resize', this.props.handleResize);
 },
 componentWillUnmount() {
  window.removeEventListener('resize');
 }})
)

https://github.com/renatorib/react-sizes - это HOC, чтобы сделать это, сохраняя при этом хорошую производительность.

import React from 'react'
import withSizes from 'react-sizes'

@withSizes(({ width }) => ({ isMobile: width < 480 }))
class MyComponent extends Component {
  render() {
    return <div>{this.props.isMobile ? 'Is Mobile' : 'Is Not Mobile'}</div>
  }
}

export default MyComponent

Попробуй это :-

      resize = () => this.forceUpdate()

componentDidMount() {
  window.addEventListener('resize', this.resize)
}

componentWillUnmount() {
  window.removeEventListener('resize', this.resize)
}

По этой причине лучше, если вы используете эти данные из данных файла CSS или JSON, а затем с этими данными устанавливаете новое состояние с помощью this.state({width: "some value",height:"some value" }); или написание кода, который использует данные ширины экрана в самостоятельной работе, если вы хотите, чтобы изображения показывались быстро

В index.js:

      function render() {
  ReactDOM.render(<App />, document.getElementById('root'));
}

render();

window.addEventListener('resize', render);

Повторный рендеринг заставляет пересчитывать все, что зависит от переменных, которые React не обнаруживает сам по себе, таких как window.innerWidth/innerHeight, localStorage и т. д., сохраняя при этом состояние приложения прежним.

Если вам нужно выполнить повторный рендеринг в других ситуациях, вы также можете экспортировать эту функцию render() и использовать ее в других местах.

Я не уверен насчет влияния этого на производительность (поскольку это может быть повторный рендеринг всего или только того, что изменилось), но для меня это кажется достаточно быстрым при изменении размера.

Для тех, кто ищет поддержку Typescript , я написал следующий хук на основе user9234721 Developer : ответа

      import { useState, useEffect } from 'react';


export const debounce = <A extends unknown[]>(callback: (...args: A) => unknown, msDelay: number) => {
    let timer: NodeJS.Timeout | undefined;

    return (...args: A) => {
        clearTimeout(timer);

        timer = setTimeout(() => {
            timer = undefined;
            callback(...args);
        }, msDelay);
    };
};

export const useWindowDimension = (msDelay = 100) => {
    const [dimension, setDimension] = useState({
        width: window.innerWidth,
        height: window.innerHeight,
    });

    useEffect(() => {
        const resizeHandler = () => {
            setDimension({
                width: window.innerWidth,
                height: window.innerHeight
            });
        };

        const handler = msDelay <= 0 ? resizeHandler : debounce(resizeHandler, msDelay);

        window.addEventListener('resize', handler);

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

    return dimension;
};

export type Dimension = ReturnType<typeof useWindowDimension>;

Приятной вещью, очевидно, является поддержка Typescript, а также возможность контролировать время задержки (вms), который по умолчанию равен100ms. Если время задержки0 or less, он не будет устранять дребезг обработчика.
Еще одно отличие состоит в том, что хук возвращает объект типаDimension, который:

      type Dimension = {
    width: number;
    height: number;
}

Таким образом, всем понятно, что на самом деле возвращает хук.

Другие вопросы по тегам