在Next.js中使用MatchMedia进行多端适配的解决方案

95
2024-06-28 18:15
5 个月前

NextJS与MatchMedia使用问题

问题分析

在我们进行应用开发的时候,往往会涉及到多端适配的开发。我们会有PC端,H5端,那在NextJs中,如何完成在不同主体项目开发的时候默认渲染哪个端的问题,首先NextJs是一个SSR框架,代码会在我们的服务器上运行,在服务器上运行是,是没有设备的device信息的。所以默认都会是false。那正常的使用react-responsive这种npm包,会一直是false,那意味着封装hooks的时候我们会封装成一个isMobile的hooks

export const useIsMobile = ()=>{
    return useMediaQuery({
        query:'(max-width: 768px)'
     });
}


如果这个是PC端的项目,那进去则没有人问题,一进去就是默认为false,如果我们的项目是以手机端为主的话,则会一直显示为false,那则会渲染PC端的代码。

那我们改如何改造呢?我发现chakra-ui的hooks能解决问题,但是引入这个也太大了。下面我们完成自己的hooks吧。

代码展示

function listener(query: MediaQueryList, callback: MediaQueryCallback) {
    try {
        query.addEventListener('change', callback);
        return () => query.removeEventListener('change', callback);
    } catch (e) {
        query.addListener(callback);
        return () => query.removeListener(callback);
    }
}

function getInitialValue(query: string, initialValue?: boolean) {
    if (typeof initialValue === 'boolean') {
        return initialValue;
    }

    if (typeof window !== 'undefined' && 'matchMedia' in window) {
        return window.matchMedia(query).matches;
    }

    return false;
}

export function useMediaQuery(
    query: string,
    initialValue?: boolean,
) {
    const [matches, setMatches] = useState(
         getInitialValue(query,initialValue)
    );
    const queryRef = useRef<MediaQueryList>();

    useEffect(() => {
        if ('matchMedia' in window) {
            queryRef.current = window.matchMedia(query);
            setMatches(queryRef.current.matches);
            return listener(queryRef.current, (event) => setMatches(event.matches));
        }

        return undefined;
    }, [query]);

    return matches;
}

解决办法

其实就是加了个默认返回值,因为用户是可以知道现在要做的是哪个为主的应用,只要加个返回值,我们就可以对这个问题简单就解决了