Jump to content
Search Community

React/Gatsby Animation based on props

Katie Nolan test
Moderator Tag

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

Hello! I have been trying to follow the GSAP/React tutorial here  and I have checked the other forum posts but I'm just not having any luck. I'd like to have a small div follow/replace the cursor on my screen. On mousemove of the parent component -  the e.clientX and e.clientY values are passed down as props to the child component New Cursor.  I set up the constructor and lifecycle functions like in the tutorial, but my replacement cursor isn't animating. 

 

If I pass a regular number as a prop it works, but it seems that something about e.ClientX and e.ClientY are preventing things from animating. I'm extremely new to React so I really appreciate any patience/help. Thank you!

 

Quote
Quote


import React from 'react';
import { css } from '@emotion/core'
import { TweenMax, TimelineLite } from 'gsap/TweenMax';


class NewCursor extends React.Component{

    constructor(props) {
        super(props);

        this.myElement = null;
        this.myTween = null;

      }

      componentDidMount(){

        // use the node ref to create the animation
        this.myTween = TweenMax
        .to(this.myElement, 1, {x: this.props.left, y: this.props.top});
      }

      componentDidUpdate(prevProps, prevState) {

        if (prevProps.left != this.props.left) {
          this.myTween.play();
        }
    }

    render(){

    return(
        <>

            <h5>x: {this.props.left}  y:{this.props.top}</h5 >

            <div
                ref={div => this.myElement = div}

                css={css`
                    background: blue;
                    width: 50px;
                    height: 50px;
                    position: absolute;
                    pointer-events: none;
                `}>
            </div>

        </>
    )
    }
};

export default NewCursor;

 

 

Also here is the parent component if that helps:

 

import React from 'react';
import Header from '../components/Header';
import NewCursor from '../components/NewCursor';
import { css } from '@emotion/core';


class NewCursorLayout extends React.Component{

    constructor(props) {
        super(props);

        this.state = {
             x: '',
             y: '',
        };

      }

      _onMouseMove = (e) =>{
        this.setState({ x: e.clientX, y: e.clientY });
      }


      componentWillUnmount(){

          const lastX = this.state.x;
          const lastY = this.state.y
          localStorage.setItem("x", lastX);
          localStorage.setItem("y", lastY);

      }

    render(){
        const { x, y } = this.state;
        const { children } = this.props;



       return(

        <>
            <div onMouseMove={this._onMouseMove.bind(this)}
            css={css`
            border: 1px solid red;
            height: 100vh;
            width: 100vw;
            max-width: 100%;
            `}>

            <NewCursor  top={y} left={x}/>
            <Header />

            <main css={css`
                width: 100%;
                max-width: 800px;
                margin: 0 auto;
                border: 2px solid pink;
            `}>
            <h3>New Cursor Layout</h3>
            {children}
            </main>
            </div>
        </>

       )
    }
};

export default NewCursorLayout;

 

Link to comment
Share on other sites

I'm not a React guy (@Rodrigo is our resident expert, and he authored that article you linked to), but my guess is that your problem is that you're creating the tween in the componentDidMount(), but then you're playing that same tween again and again in the componentDidUpdate() method. Remember, the first time a tween renders, it internally records the starting/ending values so that it can very efficiently interpolate on each "tick". Your updates are having no effect. 

 

Instead of just play()-ing that same tween instance in your componentDidUpdate(), I'd create a new one and feed in the new x/y values. The new tween will overwrite the old one anyway. 

 

Does that help at all? If you're still having trouble, it'd help a lot if you provide a reduced test case in codepen or stackblitz or something like that. 

 

Happy tweening!

  • Like 2
Link to comment
Share on other sites

Well I was creating a sample an Jack beat me to it.

 

Also a piece on friendly advice. Try to avoid updating the state of any component on events that are triggered a lot like mouse move or scroll. It could create quite a burden in the app since that component re-renders and so it will any child component in it even if they don't re-render because of the state update, Reat still will look and do a shallow comparison to see if something has to be updated. If possible try to set up an event emitter and store the mouse position outside the class, remember that you're working with ES6 modules, which means that you can export the event emitter from the main file (or other file if you want), create the event listener in the new cursor file and emit the event in the parent component, that will be far cheaper in terms of processing than updating the state on every mouse move.

 

If you take a look at this scroll spy library, you'll see that the guy does and stores all the calculations in an object and then compares those values with the ones stored. Once the scroll value exceeds the value of one of those items the state is updated only once:

 

https://github.com/makotot/react-scrollspy/blob/master/src/js/lib/scrollspy.js#L191-L201

 

Happy Tweening!!!

  • Like 3
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...