From f1622fca1f05fb84f8b27c101dd55ea00be94afa Mon Sep 17 00:00:00 2001 From: Kostiantyn Ochenash Date: Sat, 25 Feb 2023 01:05:25 +0200 Subject: [PATCH] replaces resize lib with mediaQuery matcher --- package.json | 1 - src/components/App/App.jsx | 6 +- .../BackgroundLayout/BackgroundLayout.jsx | 7 +- .../ImagesContainer/ImagesContainer.jsx | 11 ++- .../DiaryPageContent/DiaryPageContent.jsx | 11 +-- .../Calculator\320\241alorieForm.jsx" | 12 ++- .../Header/Navigation/Navigation.jsx | 23 ++---- src/components/Header/UserInfo/UserInfo.jsx | 11 +-- src/components/Modal/Modal.jsx | 10 +-- src/hooks/ui/index.js | 1 + src/hooks/ui/useMedia.js | 80 +++++++++++++++++++ src/pages/MainPage/MainPage.jsx | 3 - 12 files changed, 114 insertions(+), 62 deletions(-) create mode 100644 src/hooks/ui/useMedia.js diff --git a/package.json b/package.json index 75abd05..ed67f89 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,6 @@ "react-icons": "^4.4.0", "react-loader-spinner": "^5.1.5", "react-redux": "^8.0.2", - "react-resize-aware": "^3.1.1", "react-router-dom": "^6.3.0", "react-scripts": "5.0.1", "react-toastify": "^9.0.5", diff --git a/src/components/App/App.jsx b/src/components/App/App.jsx index fbc084c..19c3cf2 100644 --- a/src/components/App/App.jsx +++ b/src/components/App/App.jsx @@ -7,7 +7,7 @@ import { useDispatch } from 'react-redux'; import 'react-toastify/dist/ReactToastify.css'; import { ToastContainer } from 'react-toastify'; import { authOperations } from 'redux/auth'; -import { useSetDocumentTitle } from 'hooks/ui'; +import { MediaContextProvider, useSetDocumentTitle } from 'hooks/ui'; import { AppRouter } from './AppRouter'; import '../../translation/i18n'; const App = () => { @@ -22,7 +22,9 @@ const App = () => { return ( - + + + diff --git a/src/components/BackgroundLayout/BackgroundLayout.jsx b/src/components/BackgroundLayout/BackgroundLayout.jsx index 1109b07..441147b 100644 --- a/src/components/BackgroundLayout/BackgroundLayout.jsx +++ b/src/components/BackgroundLayout/BackgroundLayout.jsx @@ -1,19 +1,14 @@ import { useSelector } from 'react-redux'; -import { useLocation } from 'react-router-dom'; import ImagesContainer from './ImagesContainer'; import { Background } from './BackgroundLayout.styled'; const BackgroundLayout = ({ children }) => { const isLoggedIn = useSelector(state => state.auth.isLoggedIn); - const { pathname } = useLocation(); - const isMainPage = pathname === '/'; return ( {children} - {!isLoggedIn && ( - - )} + {!isLoggedIn && } ); }; diff --git a/src/components/BackgroundLayout/ImagesContainer/ImagesContainer.jsx b/src/components/BackgroundLayout/ImagesContainer/ImagesContainer.jsx index 069e96d..d661b6b 100644 --- a/src/components/BackgroundLayout/ImagesContainer/ImagesContainer.jsx +++ b/src/components/BackgroundLayout/ImagesContainer/ImagesContainer.jsx @@ -5,7 +5,6 @@ import leavesTabletAuth from 'images/background/leaves-tablet-auth.png'; import strawberry from 'images/background/strawberry.png'; import strawberryTablet from 'images/background/strawberry-tablet.png'; import greyBackground from 'images/background/grey-background.svg'; -import useResizeAware from 'react-resize-aware'; import { ImagesWrapper, @@ -14,15 +13,20 @@ import { BananaImg, StrawberryImg, } from './ImagesContainer.styled'; +import { useLocation } from 'react-router-dom'; +import { useMedia } from 'hooks/ui'; const DESKTOP_WIDTH_BREAKPOINT = 1280; const DESKTOP_HEIGHT_BREAKPOINT = 850; -const ImagesContainer = ({ isMainPage = false }) => { - const [resizeListener, { width, height }] = useResizeAware(); +const ImagesContainer = () => { + const { width, height } = useMedia(); const isTablet = width < DESKTOP_WIDTH_BREAKPOINT; const shouldResizeBg = height > DESKTOP_HEIGHT_BREAKPOINT; + const { pathname } = useLocation(); + const isMainPage = pathname === '/'; + const strawberryImageSource = !isTablet ? strawberry : isMainPage @@ -37,7 +41,6 @@ const ImagesContainer = ({ isMainPage = false }) => { return ( - {resizeListener} { const { t } = useTranslation(); const [showModal, setShowModal] = useState(false); @@ -50,14 +47,12 @@ export const DiaryPageContent = () => { setShowModal(!showModal); }; - const [resizeListener, { width }] = useResizeAware(); - const isMobile = width < TABLET; + const { isMobile } = useMedia(); + const [, openMobileModal] = useMobileModal(); return ( - {resizeListener} - { const { t } = useTranslation(); const [selectedTypeBlood, setSelectedTypeBlood] = useState(1); - const [resizeListener, { width }] = useResizeAware(); + const { isMobile } = useMedia(); const dispatch = useDispatch(); const isLoggedIn = useSelector(getIsLoggedIn); - const mobileWidth = width <= 767; + const [, openMobileModal] = useMobileModal(); const validationSchema = yup.object({ @@ -72,10 +71,10 @@ const CalculatorСalorieForm = ({ openModal, getPrivatDailyNorma }) => { await getPrivatDailyNorma(paramsUser); } - if (formik.dirty && !isLoggedIn && !mobileWidth) { + if (formik.dirty && !isLoggedIn && !isMobile) { await openModal(); } - if (formik.dirty && !isLoggedIn && mobileWidth) { + if (formik.dirty && !isLoggedIn && isMobile) { await openMobileModal(); } resetForm(); @@ -84,7 +83,6 @@ const CalculatorСalorieForm = ({ openModal, getPrivatDailyNorma }) => { return (
- {resizeListener} { ); }; -const TABLET = 768; -const DESKTOP = 1280; - const Header = () => { const { t } = useTranslation(); - const [resizeListener, { width }] = useResizeAware(); - const mobileWidth = width < TABLET; - const tabletWidth = width >= TABLET && width < DESKTOP; - const desktopWidth = width >= DESKTOP; + const { isMobile, isTablet, isDesktop } = useMedia(); const isLogged = useSelector(getIsLoggedIn); const [showMobileModal, , hideMobileModal] = useMobileModal(); @@ -109,8 +102,6 @@ const Header = () => { return (
- {resizeListener} - @@ -121,7 +112,7 @@ const Header = () => { {!isLogged && } - {isLogged && mobileWidth && ( + {isLogged && isMobile && (
{
)} - {isLogged && tabletWidth && ( + {isLogged && isTablet && ( <> { )} - {isLogged && desktopWidth && ( + {isLogged && isDesktop && ( <>
@@ -166,13 +157,13 @@ const Header = () => { - {isLogged && mobileWidth && ( + {isLogged && isMobile && ( )} - {!isLogged && mobileWidth && showMobileModal && ( + {!isLogged && isMobile && showMobileModal && ( diff --git a/src/components/Header/UserInfo/UserInfo.jsx b/src/components/Header/UserInfo/UserInfo.jsx index 1e5ab40..d2b9d78 100644 --- a/src/components/Header/UserInfo/UserInfo.jsx +++ b/src/components/Header/UserInfo/UserInfo.jsx @@ -1,4 +1,3 @@ -import useResizeAware from 'react-resize-aware'; import { useSelector } from 'react-redux'; import { getName } from 'redux/auth/authSelector'; import { @@ -9,22 +8,18 @@ import { ReturnButtonWrapper, } from './UserInfo.styled'; import { Alert } from './Alert'; -import { useMobileModal } from 'hooks/ui'; +import { useMedia, useMobileModal } from 'hooks/ui'; import IconButton from 'components/IconButton'; -const TABLET = 768; - export default function UserInfo() { - const [resizeListener, { width }] = useResizeAware(); - const isMobile = width < TABLET; + const { isMobile } = useMedia(); + const name = useSelector(getName); const [showMobileModal, , hideMobileModal] = useMobileModal(); return ( - {resizeListener} - {showMobileModal && isMobile && ( } onClick={hideMobileModal} /> diff --git a/src/components/Modal/Modal.jsx b/src/components/Modal/Modal.jsx index ed8f0ae..593505c 100644 --- a/src/components/Modal/Modal.jsx +++ b/src/components/Modal/Modal.jsx @@ -3,9 +3,8 @@ import Dialog from '@mui/material/Dialog'; import DialogContent from '@mui/material/DialogContent'; import { ModalContent } from './ModalContent/ModalContent'; -import useResizeAware from 'react-resize-aware'; import { MobileModal } from 'components/MobileModal'; -import { useMobileModal } from 'hooks/ui'; +import { useMedia, useMobileModal } from 'hooks/ui'; const MuiDialog = styled(Dialog)(({ theme }) => ({ '& .MuiDialogContent-root': { @@ -15,8 +14,7 @@ const MuiDialog = styled(Dialog)(({ theme }) => ({ })); export const Modal = ({ showModal, setShowModal }) => { - const [resizeListener, { width }] = useResizeAware(); - const mobileWidth = width <= 767; + const { isMobile } = useMedia(); const [showMobileModal, , hideMobileModal] = useMobileModal(); @@ -30,9 +28,7 @@ export const Modal = ({ showModal, setShowModal }) => { return (
- {resizeListener} - - {!mobileWidth ? ( + {!isMobile ? (
window.matchMedia(query); +const isTabletMQ = makeMediaQueryList(tabletMQ); + +/** + * @param {boolean} matches + * @returns {"tablet" | "mobile" | "desktop"} string + */ +const checkMedia = matches => { + if (matches) return 'tablet'; + return window.innerWidth < TABLET ? 'mobile' : 'desktop'; +}; + +const mediaInitState = { + media: checkMedia(isTabletMQ.matches), +}; + +const initState = { + width: window.innerWidth, + height: window.innerHeight, + isMobile: mediaInitState.media === 'mobile', + isTablet: mediaInitState.media === 'tablet', + isDesktop: mediaInitState.media === 'desktop', +}; + +const useResizeEffect = () => { + const [{ width, height, isMobile, isTablet, isDesktop }, setMedia] = + useState(initState); + + useEffect(() => { + const updateIsTabletMQ = ({ matches }) => { + const checked = checkMedia(matches); + + const newMedia = { + width: window.innerWidth, + height: window.innerHeight, + isMobile: checked === 'mobile', + isTablet: checked === 'tablet', + isDesktop: checked === 'desktop', + }; + + setMedia(newMedia); + }; + + isTabletMQ.addEventListener('change', updateIsTabletMQ, { passive: true }); + return () => { + isTabletMQ.removeEventListener('change', updateIsTabletMQ); + }; + }, []); + + return useMemo( + () => ({ + width, + height, + isMobile, + isTablet, + isDesktop, + }), + [height, isDesktop, isMobile, isTablet, width] + ); +}; + +export const MediaContext = createContext(initState); + +export const MediaContextProvider = ({ children }) => { + const context = useResizeEffect(); + return ( + {children} + ); +}; + +export const useMedia = () => useContext(MediaContext); diff --git a/src/pages/MainPage/MainPage.jsx b/src/pages/MainPage/MainPage.jsx index 6596435..d7cdc0e 100644 --- a/src/pages/MainPage/MainPage.jsx +++ b/src/pages/MainPage/MainPage.jsx @@ -4,13 +4,11 @@ import { PageContainer, FormContainer } from './MainPage.styled'; import Container from 'components/Container'; import { Modal } from 'components/Modal'; -import useResizeAware from 'react-resize-aware'; import CalculatorСalorieForm from 'components/Forms/CalculatorСalorieForm/CalculatorСalorieForm'; import { useMobileModal } from 'hooks/ui'; import { useTranslation } from 'react-i18next'; const MainPage = () => { - const [resizeListener] = useResizeAware(); const [showModal, setShowModal] = useState(false); const openModal = () => setShowModal(prev => !prev); @@ -29,7 +27,6 @@ const MainPage = () => { return ( - {resizeListener}