0

OK guys, so I'm noob in React, and I know that I'm mistaken something, but I can't see what.

I put loading spinners between my pages and no problems, until this page :

So I have this page that is scrolling on X axe and a logo spinning during scroll, until know, all was working correctly. And there is the code without the loading spinner :

import React, { useEffect, useRef } from "react";
import styled, { ThemeProvider } from "styled-components";
import { DarkTheme } from "./Themes";
import {motion} from 'framer-motion';
import LogoComponent from '../subComponents/LogoComponent';
import SocialIcons from '../subComponents/SocialIcons';
import PowerButton from '../subComponents/PowerButton';
import { Work } from '../data/WorkData';
import Card from "../subComponents/Card";
import { Umbrella } from "./AllSvgs";
import BigTitle from "../subComponents/BigTitle";

const Box = styled.div`
background-color: ${props => props.theme.body};

height: 400vh;
position: relative;
display: flex;
align-items: center; 

`

const Main = styled(motion.ul)`
position: fixed;
top: 12rem;
left: calc(10rem + 15vw);
height: 40vh;
display: flex;

color: white;
` 

const Rotate = styled.span`
display: block;
position: fixed;
right: 1rem;
bottom: 1rem;
width: 80px;
height: 80px;
z-index:1;
`

// Framer-motion configuration

const container = {
    hidden: {opacity:0},
    show: {
        opacity:1,

        transition: {
            staggerChildren:0.5,
            duration:0.5,
        }
    }
}


const WorkPage = () => {

    const ref = useRef(null);
    const umbrella = useRef(null);

    useEffect(() => {

            let element = ref.current;
            
            const rotate = () => {
                element.style.transform = `translateX(${-window.scrollY}px)`
    
                umbrella.current.style.transform = `rotate(` + -window.scrollY + 'deg)'
            }
    
            window.addEventListener('scroll', rotate)
    
            return () => window.removeEventListener('scroll', rotate)

    }, [])


    return (
        <ThemeProvider theme={DarkTheme}>

            <Box>
                <LogoComponent theme='dark'/>
                <SocialIcons theme='dark'/>
                <PowerButton />

                <Main ref={ref}  variants={container} initial='hidden' animate='show' >
                    {
                        Work.map( d =>
                            <Card key={d.id} data={d} />
                        )
                    }
                </Main>

                <Rotate ref={umbrella}>
                    <Umbrella width={80} height={80} fill={DarkTheme.theme} />
                </Rotate>

                <BigTitle text="PROJETS" top="10%" right="20%" />

            </Box>
            
        </ThemeProvider>
    )
}

export default WorkPage

Then I put the code with the same logic than the other pages that are working :

import React, { useEffect, useRef, useState } from "react";
import styled, { ThemeProvider } from "styled-components";
import { DarkTheme } from "./Themes";
import {motion} from 'framer-motion';
import RingLoader from "react-spinners/RingLoader";
import { css } from "@emotion/react";
import LogoComponent from '../subComponents/LogoComponent';
import SocialIcons from '../subComponents/SocialIcons';
import PowerButton from '../subComponents/PowerButton';
import { Work } from '../data/WorkData';
import Card from "../subComponents/Card";
import { Umbrella } from "./AllSvgs";
import BigTitle from "../subComponents/BigTitle";

const Box = styled.div`
background-color: ${props => props.theme.body};

height: 400vh;
position: relative;
display: flex;
align-items: center; 

`

const Main = styled(motion.ul)`
position: fixed;
top: 12rem;
left: calc(10rem + 15vw);
height: 40vh;
display: flex;

color: white;
` 

const Rotate = styled.span`
display: block;
position: fixed;
right: 1rem;
bottom: 1rem;
width: 80px;
height: 80px;
z-index:1;
`

const override = css`
position: absolute;
bottom: 10%;
right: 10%;
`

// Framer-motion configuration

const container = {
    hidden: {opacity:0},
    show: {
        opacity:1,

        transition: {
            staggerChildren:0.5,
            duration:0.5,
        }
    }
}


const WorkPage = () => {

    const [loading, setLoading] = useState(false);

    useEffect(() => {
            setLoading(true)
            setTimeout(() => {
                setLoading(false)
            }, 2000)
            
    }, [])

    const ref = useRef(null);
    const umbrella = useRef(null);

    useEffect(() => {

            let element = ref.current;
            
            const rotate = () => {
                element.style.transform = `translateX(${-window.scrollY}px)`
    
                umbrella.current.style.transform = `rotate(` + -window.scrollY + 'deg)'
            }
    
            window.addEventListener('scroll', rotate)
    
            return () => window.removeEventListener('scroll', rotate)

    }, [])


    return (
        <ThemeProvider theme={DarkTheme}>
            {
                loading ?
                <RingLoader 
                color={'#000'} 
                loading={loading}  
                size={60}
                css={override}
                />

                :

                <Box>
                    <LogoComponent theme='dark'/>
                    <SocialIcons theme='dark'/>
                    <PowerButton />

                    <Main ref={ref}  variants={container} initial='hidden' animate='show' >
                        {
                            Work.map( d =>
                                <Card key={d.id} data={d} />
                            )
                        }
                    </Main>

                    <Rotate ref={umbrella}>
                        <Umbrella width={80} height={80} fill={DarkTheme.theme} />
                    </Rotate>

                    <BigTitle text="PROJETS" top="10%" right="20%" />

                </Box>
            }
        </ThemeProvider>
    )
}

export default WorkPage

And the scroll is not working anymore. The logo is still spinning. I try to put in conditions, but nope. Put the useState on true, but then I have an error on the rotate func :

TypeError: Cannot read properties of null (reading 'style')
rotate
src/components/WorkPage.js:89
  86 |         let element = ref.current;
  87 |         
  88 |         const rotate = () => {
> 89 |             element.style.transform = `translateX(${-window.scrollY}px)`
     | ^  90 | 
  91 |             umbrella.current.style.transform = `rotate(` + -window.scrollY + 'deg)'
  92 |         }

I don't see what I'm missing... Thanks y'all

davidhu
  • 9,523
  • 6
  • 32
  • 53

1 Answers1

0

In your second example code (where you added loading and setLoading from the useState hook), the <Box> component (which contains the <Main ref={ref}... component) doesn't get rendered when loading is set to true (and you're setting it to true in your first useEffect).

Since the <Main ref={ref}... component isn't being rendered, the line let element = ref.current will initialize element as null. (that's why you're getting that error)

  • Ok that make sense. But i put the setTimeout which change it to false after 2 seconds, and that's why there is the condition because when the loader is timedout, the page loads. all the page is displaying well, the logo is spinning when I'm scrolling, just the scrollX is not working so the page is static – Adrien Dubois Dec 14 '21 at 15:58
  • The problem is that the first time the `useEffect` function that contains the `let element = ref.current` code runs -> `ref` won't exist due to your loading indicator. – Jason Rastovski Dec 14 '21 at 16:12
  • One suggestion would be to set a dependency for that second `useEffect` on your `loading` property. Add in a conditional `if` statement inside of that second `useEffect` to ensure `ref.current` is not null. – Jason Rastovski Dec 14 '21 at 16:13
  • `useEffect(() => { if (ref.current !== null) { // setup your scrolling listener here } }, [loading])` – Jason Rastovski Dec 14 '21 at 16:15
  • Man, you're a genius I was thinking to the logic and you did that !! Thanks it works great, and it will help me to the future !! – Adrien Dubois Dec 14 '21 at 16:24
  • :-) awesome -> glad i could help. – Jason Rastovski Dec 14 '21 at 17:05