Search code examples
javascriptreactjsnext.jsframer-motion

"window.innerWidth < 768" in Next.js with Framer Motion


I would like to control when an animation (Framer Motion) can run using window.innerWidth, but in Next.js I get the following error message:

ReferenceError: window is not defined

This is a simplified version of my component named ValuesSection.jsx:

import React, { useEffect } from "react";
import { useInView } from "react-intersection-observer";
import { motion, useAnimation } from "framer-motion";

export default function ValuesSection() {
  const controls = useAnimation();
  const [ref, inView] = useInView();
  const MobileView = {};
  const isMobile = window.innerWidth < 768;
  if (!isMobile) {
    MobileView = {
      visible: { y: 0, scale: 1 },
      hidden: { y: 250, scale: 0 },
    };
  }

  useEffect(() => {
    if (inView) {
      controls.start("visible");
    }
  }, [controls, inView]);

  return (
<>
 <motion.div
  key={value.name}
  ref={ref}
  animate={controls}
  initial="hidden"
  variants={MobileView}
 >Some content</motion.div>
</>

Can you help me understand what I'm doing wrong? And if you are able to provide me with a working example, it would be great and appreciated.


Solution

  • Best way of using screen size in next.js projects is that you can instead use a Hook from materiial ui that represents true or false when screen width is bigger or smaller than defined value and in my opinion it's better than the window because it has a lot of options that you can use here is what you should do step by step

    first install material ui if you didn't already

    // with npm
    npm install @material-ui/core
    
    // with yarn
    yarn add @material-ui/core
    

    then import and define it inside of your component

    import { useMediaQuery } from "@material-ui/core";
    
    
    export default function ValuesSection() {
    
    const IsTabletOrPhone = useMediaQuery("(max-width:1024px)");
    

    now if you screen size is bigger than 1024px it returns false, otherwise it returns true
    so you can use it

      if (!IsTabletOrPhone) {
        MobileView = {
          visible: { y: 0, scale: 1 },
          hidden: { y: 250, scale: 0 },
        };
      }
    

    Update:

    Maybe it's because i assigned it with a uppercase letter, you can try changing the name to isTabletOrPhone with lowercase, if that didn't work try to change it to let instead

    let isTabletOrPhone = useMediaQuery("(max-width:1024px)");