skip to Main Content

When I use useMediaQuery from Material UI in my React app in the top level component (App) of my app, the query doesn’t work (value doesn’t update on window resize) and causes rendering issues (when using Chrome’s dev tools mobile screen emulators). But if I move the query in to a child component (AppContainer), it works. Is it because the containing component needs to have some kind of size attributes?
Here is my top level component with the query:

import firebase from './firebase/Firebase';
import {useState} from "react";
import {AuthContext} from "./contexts/AuthContext";
import useMediaQuery from "@mui/material/useMediaQuery";

function App() {

    const [isLoggedIn, setIsLoggedIn] = useState(true);
    const [user, setUser] = useState(null);
    const isWideScreen = useMediaQuery('(min-width: 500px)', {noSsr: true});

    firebase.auth().onIdTokenChanged(async (userObject) => {
        setIsLoggedIn(!!userObject);
        if (userObject){
            await localStorage.setItem('accessToken', await userObject.getIdToken());
        }
        setUser(userObject);
    })

    return (
        <AuthContext.Provider value={{ isLoggedIn , user }}>
            <>
                <span>{'isWideScreen:'+ isWideScreen.toString()}</span>
            </>
        </AuthContext.Provider>
    );

}

export default App;

Update: I have found that if I COMMENT OUT the firebase auth onIdTokenChanged line of code, the media query works. But if I keep the firebase auth code in this component, the media query fails to update on resize.

2

Answers


  1. Chosen as BEST ANSWER

    As @LindaPaiste suggested, moving the firebase auth handler code into a useEffect fixed the media query issue.

        useEffect(() => {
        firebase.auth().onIdTokenChanged(async (userObject) => {
            setIsLoggedIn(!!userObject);
            if (userObject){
                await localStorage.setItem('accessToken', await userObject.getIdToken());
            }
            setUser(userObject);
        });
    },[])
    

  2. What I’m seeing here is that you have some wonky stuff relating to the Firebase setup. I can’t say for sure that this will fix your MUI problems, but I would give it a try.

    You only need to set the onIdTokenChanged handler for your Firebase instance one time. The callback function will still run every time that the id token is changed. You should do this inside of a useEffect hook with an empty dependency array [] to run this once at mount (you could use dependencies [setIsLoggedIn, setUser] and it will behave the same, as these functions never change).

    The await inside of localStorage.setItem is confusing. I would move this to a separate line. You do not need to await localStorage.setItem because that is a synchronous operation.

    Try this:

    import firebase from './firebase/Firebase';
    import { useEffect, useState } from 'react';
    import { AuthContext } from './contexts/AuthContext';
    import useMediaQuery from '@mui/material/useMediaQuery';
    
    function App() {
    
        const [isLoggedIn, setIsLoggedIn] = useState(true);
        const [user, setUser] = useState(null);
        const isWideScreen = useMediaQuery('(min-width: 500px)', { noSsr: true });
    
        useEffect(() => {
            firebase.auth().onIdTokenChanged(async (userObject) => {
                setIsLoggedIn(!!userObject);
                setUser(userObject);
                if (userObject) {
                    const token = await userObject.getIdToken();
                    localStorage.setItem('accessToken', token);
                }
            });
        }, []);
    
        return (
            <AuthContext.Provider value={{ isLoggedIn, user }}>
                <>
                    <span>{'isWideScreen:' + isWideScreen.toString()}</span>
                </>
            </AuthContext.Provider>
        );
    
    }
    
    export default App;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search