TaiwoJazz Posted November 7, 2022 Share Posted November 7, 2022 Hi everyone, I feel like I'm just turning in a circle here for almost a week even after enrolling for Carl's Creative Coding Club course.. He's definitely doing a great job but since all gsap codes are written in vanilla js... Also, i have gone through the GSAP + React article of gsap learns section but it's not just coming in handy... I really want to master gsap using react... So i just wanna ask if anyone knows or has any gsap course that specifically focuses on React... Either on Udemy or anywhere.. A link will be appreciated... Thanks in advance... Link to comment Share on other sites More sharing options...
GreenSock Posted November 7, 2022 Share Posted November 7, 2022 Welcome, @TaiwoJazz. You said you read this article, right?: Do you mind me asking what exactly you WISH was covered there (and wasn't)? Are you just looking for more demos or walk-throughs with real projects? We tried really hard to make the article rich and as concise as possible. It's difficult to find the right balance between "overwhelming...eyes glazing over from so much info" and "too concise...I wish there was more info". What exactly are you struggling with? Link to comment Share on other sites More sharing options...
TaiwoJazz Posted November 7, 2022 Author Share Posted November 7, 2022 Thanks for the reply... As i said, i really took time to read the React article and followed the step by step guide... For example, targeting classes and id with gsap.context() works in some places and through"Invalid Scope, Target error is some places in my code" These errors are not covered and I'm sure I'm following everything properly... Sorry I can't convert this code to codepen... But I'm not sure why I'm getting target error here.. import React, {useRef, useLayoutEffect} from 'react'; import gsap from 'gsap'; import useLoader from '../../hooks/use-loader'; import useAnimatedLetters from '../../hooks/use-animatedletters'; import Bio from './Bio'; const About = () => { const aboutme = useRef(); const {loading, loader} = useLoader(); useLayoutEffect(() => { let ctx = gsap.context(() => { gsap .timeline({ defaults: {opacity: 0, ease: 'back', duration: 6}, }) .from('#about', {ease: 'linear', autoAlpha: 0}); }, aboutme); return () => ctx.revert(); }, []); let string = 'About Me'; const {letters: Heading} = useAnimatedLetters({ strArray: string.split(''), index: 1, }); return loading ? ( loader ) : ( <section ref={aboutme} > <div className="invisible px-6 lg:ml-16 flex flex-col lg:flex-row items-center justify-center gap-28 lg:40 xl:gap-72 h-full lg:h-screen mb-24 lg:mb-0"> <div id="about"> <h2 className="text-lightMode-100 text-3xl font-bold w-fit mb-6 mt-32 lg:mt-0"> {Heading} </h2> <Bio /> </div> </div> </section> ); }; export default About; Link to comment Share on other sites More sharing options...
Rodrigo Posted November 7, 2022 Share Posted November 7, 2022 Hi, I've been using GSAP in React apps for over 5 years and have done my fare share of stuff with them. In my experience there is no such resource for a very simple reason: GSAP is framework agnostic, so is thought to work with every UI Framework that you can find: React, Vue, Svelte, Angular, Inferno, Alpine, name-it. The biggest struggle I think React users have, especially those that are just starting, is think in terms of how to correctly architect and layout their React apps, especially when those apps have a lot of moving parts, such as routing, API calls, other 3rd party libraries and packages, etc. If you are just starting with React you could take a course in Udemy either one created by Stephen Grider or Brad Traversy. I took one course of Stephen Grider when I needed to learn how to use NestJS for a full stack project and I think that He does a good job in explaining and showing you how to do stuff with detail but not too slow. As far as Brad goes, I've seen a few videos in youtube and think he does a good job as well, IDK how much detail he goes into on his courses so I couldn't compare them. If you're looking for something closer to Carl's teaching style I'd say go with Stephen Grider. Finally when starting, always go from small to big, never try to do too much. This is a learning process that has a curve, so as you start simple you begin with the easy stuff and then you add more complex stuff into the mix. Let us know if you have more questions. Happy Tweening! 1 Link to comment Share on other sites More sharing options...
GreenSock Posted November 7, 2022 Share Posted November 7, 2022 To answer your question about why your code was throwing an error about an invalid scope, it looks like your component renders a completely different thing if it's "loading", so when your useLayoutEffect() is called, there is no aboutme element at all. It doesn't exist, but you're asking GSAP to look inside of that for '#about'. See what I mean? 1 Link to comment Share on other sites More sharing options...
Solution Rodrigo Posted November 7, 2022 Solution Share Posted November 7, 2022 Indeed Jack is right. The first time your app runs the reference for the element is undefined. Just pass the loaded state as a dependency in your use layout hook and it should work: useLayoutEffect(() => { let ctx; if (loading) { ctx = gsap.context(() => { gsap .timeline({ defaults: {opacity: 0, ease: 'back', duration: 6}, }) .from('.about', {ease: 'linear', autoAlpha: 0}); }, aboutme); } return () => ctx && ctx.revert(); }, [loading]); Here is a live example: https://codesandbox.io/s/gsap-react-setup-forked-e77o04 It uses a set timeout instance to create the illusion of an API call, but it should illustrate the point. Happy Tweening! 1 1 Link to comment Share on other sites More sharing options...
TaiwoJazz Posted November 7, 2022 Author Share Posted November 7, 2022 @Rodrigo Thanks a lot for that input... I've been using react for 6 months... Still a not a pro but I'm getting there and i took a very good course and always try to make my code base readable... I really appreciate your input, you are a mentor to recon with.. I will work on it now... Thanks a lot guys... Hopefully i should be in Green Club Sock soon 😂😂 1 Link to comment Share on other sites More sharing options...
TaiwoJazz Posted November 7, 2022 Author Share Posted November 7, 2022 @Rodrigo Sorry, Please i'm back again... I want to understand why the first code works just fine and the second code still shows target not found.. Based on the example you gave me above.. This code works just fine with no issues.. import React, {useRef, useLayoutEffect} from 'react'; import gsap from 'gsap'; import useLoader from '../../hooks/use-loader'; import useAnimatedLetters from '../../hooks/use-animatedletters'; import Bio from './Bio'; const About = () => { const aboutMe = useRef(); const {loading, loader} = useLoader(); useLayoutEffect(() => { let ctx; if (!loading) { ctx = gsap.context(() => { gsap .timeline({ defaults: {opacity: 0, ease: 'back', duration: 1}, }) .from('#about', {ease: 'linear', autoAlpha: 0}) .from('.content > p', {x: -100, stagger: 0.3}); }, aboutMe); } return () => ctx && ctx.revert(); }, [loading]); let string = 'About Me'; const {letters: Heading} = useAnimatedLetters({ strArray: string.split(''), index: 1, }); return loading ? ( loader ) : ( <section ref={aboutMe}> <div id="about" className="invisible px-6 lg:ml-16 flex flex-col lg:flex-row items-center justify-center gap-28 lg:40 xl:gap-72 h-full lg:h-screen mb-24 lg:mb-0"> <div> <h2 className="text-lightMode-100 text-3xl font-bold w-fit mb-6 mt-32 lg:mt-0"> {Heading} </h2> <Bio className="content" /> </div> </div> </section> ); }; export default About; But this code doesn't work.. Only the first element (#contact) in the timeline work.. The rest element in the timeline kept showing target not found... What may be the issue here... I think i'm doing everything right here and everything should work as expected... import {useRef, useLayoutEffect} from 'react'; import gsap from 'gsap'; import useLoader from '../../hooks/use-loader'; import Heading from './Heading'; import Form from './Form/Form'; const Contact = () => { const contactMe = useRef(); const {loading, loader} = useLoader(); useLayoutEffect(() => { let ctx; if (!loading) { ctx = gsap.context(() => { gsap .timeline({ defaults: {opacity: 0, ease: 'back', duration: 1}, }) .from('#contact', {ease: 'linear', autoAlpha: 0}) .from('#content > p', {x: -100, stagger: 0.3}) .from('.form div', {x: 100}, '<') .from('.form > input', {x: 100, stagger: 0.2}, '-=0.8') .from('.form textarea', {x: 100}, '-=0.8') .from('.form span', {x: 100}, '-=0.8'); }, contactMe); } return () => ctx && ctx.revert(); }, [loading]); return loading ? ( loader ) : ( <section ref={contactMe}> <div id="contact" className="invisible"> <div className=" flex flex-col lg:flex-row items-center justify-center h-fit lg:h-screen lg:pl-16 px-8 w-screen gap-20 lg:pb-24 overflow-x-hidden"> <Heading id="content" /> <Form className="form" /> </div> </div> </section> ); }; export default Contact; Link to comment Share on other sites More sharing options...
Rodrigo Posted November 7, 2022 Share Posted November 7, 2022 Please create a minimal demo in codesanbox in order to see that. In the effect hook loading should be either true or false in order to run that. Also you can log in the console a query selector for the selector texts you're passing to GSAP. Link to comment Share on other sites More sharing options...
TaiwoJazz Posted November 8, 2022 Author Share Posted November 8, 2022 @Rodrigo I just created a minimal demo on codesandbox... As i said, both the about and contact pages' gsap codes are almost the same thing but somehow, the about section works fine while the contact section doesn't work... I tried to stimulate the exact code i have... Thanks... Link to comment Share on other sites More sharing options...
Rodrigo Posted November 8, 2022 Share Posted November 8, 2022 You have a couple of syntax errors. FormContent.jsx // id is a parameter, you need to destructure the props object // Wrong const FormContent = (id) => {} // Right const FormContent = ({ id }) => {} Form.jsx // Wrong const Form = (ClassName) => {} // Right const Form = ({ className }) => {} // In this case the prop you're passing in the parent is camelCased <Form className="form" /> // className not ClassName Fixing those seems to make it work the way you intend. Happy Tweening! Link to comment Share on other sites More sharing options...
TaiwoJazz Posted November 8, 2022 Author Share Posted November 8, 2022 @Rodrigo Thanks a lot.. I appreciate your time... Everything now works find in this minimal demo... GSAP has the best forum... 1 Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now