Когда я использую useMediaQuery из пользовательского интерфейса материала в своем приложении React в компоненте верхнего уровня (приложении) моего приложения, запрос не работает (значение не обновляется при изменении размера окна) и вызывает проблемы с рендерингом (при использовании мобильных инструментов разработки Chrome). эмуляторы экрана). Но если я перенесу запрос в дочерний компонент (AppContainer), он сработает. Это потому, что содержащий компонент должен иметь какие-то атрибуты размера?
Вот мой компонент верхнего уровня с запросом:
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;
Обновление: я обнаружил, что если я закомментирую строку кода Firebase auth onIdTokenChanged, медиа-запрос будет работать. Но если я сохраню код аутентификации Firebase в этом компоненте, медиа-запрос не сможет обновиться при изменении размера.
Я убедился, что проблема не в поставщике контекста. Даже если я удалю контекст и использую его в качестве своего App.js, значение isWideScreen не обновляется при изменении размера окна в эмуляторе мобильного экрана Chrome dev Tools. Я обновлю исходное сообщение своим кодом.
@NicholasTower Посмотрите мое обновление к посту. Я добавил код Firebase, который, похоже, вызывает проблему.
Попробуйте поместить весь этот блок кода Firebase в useEffect, который запускается один раз при монтировании. Эффект будет обрабатывать добавление обработчика событий onIdTokenChanged к объекту Firebase. Функция обратного вызова по-прежнему будет запускаться каждый раз, когда пользователь меняет Firebase.





Как предложил @LindaPaiste, перемещение кода обработчика аутентификации Firebase в useEffect устранило проблему медиа-запроса.
useEffect(() => {
firebase.auth().onIdTokenChanged(async (userObject) => {
setIsLoggedIn(!!userObject);
if (userObject){
await localStorage.setItem('accessToken', await userObject.getIdToken());
}
setUser(userObject);
});
},[])
Я вижу здесь некоторые странные вещи, связанные с настройкой Firebase. Я не могу с уверенностью сказать, что это решит ваши проблемы с MUI, но я бы попробовал.
Вам нужно установить обработчик onIdTokenChanged для вашего экземпляра Firebase только один раз. Функция обратного вызова по-прежнему будет выполняться каждый раз при изменении токена идентификатора. Вы должны сделать это внутри хука useEffect с пустым массивом зависимостей [], чтобы запустить его один раз при монтировании (вы можете использовать зависимости [setIsLoggedIn, setUser], и он будет вести себя так же, поскольку эти функции никогда не меняются).
await внутри localStorage.setItem сбивает с толку. Я бы вынес это в отдельную строку. Вам не нужно awaitlocalStorage.setItem, потому что это синхронная операция.
Попробуй это:
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;
Я не могу воспроизводить потомство. Возможно, проблема возникает тогда, когда вы пытаетесь получить доступ к ScreenContext. Можете ли вы показать код, который вызывает
useContext(ScreenContext)?