Пользовательский хук обновляет либо родительский, либо дочерний компонент, но не оба

#reactjs #react-hooks

#reactjs #реагирующие хуки

Вопрос:

Моя цель — использовать хук, который получит текущее состояние в любой части приложения. Я знаю, что мы можем использовать useContext для этого, но я видел, что многие библиотеки делают то же самое с пользовательским хуком, например useHook . Для простого хука ниже либо дочерний, либо родительский компонент обновляется с новым размером ширины экрана при изменении ширины экрана, но не оба вместе! Вот https://codesandbox.io/s/priceless-resonance-w6qui?file=/src/App.js для приведенного ниже и демо-версии находится по адресу: https://w6qui.csb.app /

 import React, { useState } from "react";

const useHook = () => {
  const [screenWidth, setScreenWidth] = useState(window.screen.width);

  window.onresize = () => setScreenWidth(window.screen.width);

  return { screenWidth };
};

function Child() {
  const { screenWidth } = useHook();

  return <div>Child ScreenWidth: {screenWidth}</div>;
}

function App() {
  const { screenWidth } = useHook();

  return (
    <div>
      Parent screenWidth: {screenWidth} <Child />
    </div>
  );
}

export default App;
  

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

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

Ответ №1:

Потому что либо дочерний, либо родительский компонент override (re-declare) вызовет обратный window.onresize вызов . Я предлагаю вам использовать прослушиватель событий для изменения размера обратного вызова:

 const useHook = () => {
    const [screenWidth, setScreenWidth] = useState(window.screen.width);

    useEffect(() => {
        function updateSize() {
            setScreenWidth(window.screen.width);
        }
        
        window.addEventListener('resize', updateSize);
        updateSize();
        return () => window.removeEventListener('resize', updateSize);
    }, []);

    return { screenWidth };
};
  

Комментарии:

1. Спасибо за объяснение! Теперь работает отлично. 🙂