Jump to content
Search Community

NickWoodward

Premium
  • Posts

    221
  • Joined

  • Last visited

About NickWoodward

Recent Profile Visitors

1,245 profile views

NickWoodward's Achievements

  1. And I don't have a problem with that at all. But I can't make the choice if I don't know the choice is there to be made 🤷‍♂️ - especially when rightly or wrongly, things like abstraction are pretty big in react. I wasn't here to argue in favour of either approach, outside of the limitations my current-app choices have obviously imposed. I'm certainly not wedded to them, but to some extent I do have to work round the project as it exists today I guess that was part of the reason for my reply to you: It felt a bit harsh to be directed to learn fundamental react concepts because of that structure? I showed it just to give an idea of my app's layout - if you'd said "sections can't be abstract or dumb in this scenario" I'd have asked if I could wrap it and include the animation there, or for a small example of how you'd structure it, for example. I admit my question was initially poorly formed - I missed the cleanup return function and that the selector shouldn't have been working at all - so I can understand it was probably a frustrating question. Sorry for that. If not, it was a misunderstanding on my part, but from my perspective it came across that way. I appreciate the apology either way, and don't think it intentional now - but worth checking because it at least appeared as if I genuinely had annoyed you. In fact I think the surprise added to my response - because your description of this forum is accurate. It is a welcoming place, you're right 1: As the parent to Box will the `<Section>` component ever not be available though, outside of the first render? (even that still seems to be - think that's SSR magic) 2: Passing a ref of Section to Box for scope? - again, maybe ignorance, but I'm not too sure why this would get much more complicated? 3: I'm not entirely sure what you mean by flattening in practical terms though? Wasn't #1 sort of the question I was asking? That there might be more to think about than simply omitting scope? #2 I agree, feels overly complex passing the parent to the child (and I just don't like it), and 3 requires a bit of a rework for me, or placing the animations in the astro file - which I've had some bad experiences with when using react. 3 I guess could be achieve by wrapping the dumb section component with another component too, but I'm guessing you wouldn't be a fan. Anything wrong with just moving the trigger to become the element itself and tweaking the start/end properties? Because that seems like the best of both right now
  2. It's not what I want to do particularly, but it's how I might have to I guess? That's exactly what I was double checking with the selectors though, so thanks! Re being more reacty & encapsulation - definitely, you're right, reaching outside the component isn't reacty. But I mean that gsap selector is a little bit magic/non reacty, I've just confused SSR/astro magic with gsap magic I guess? I did try to clarify if I should make the elements themselves (in this case the Box) the trigger instead though. So the animation, ScrollTrigger and trigger element would all be in the Box. Sound right? I'm just not sure about having to place the Box's animations in Section, just to have access to the trigger element? That doesn't feel like the Box is very well encapsulated either now? Rather than moving its animations to its parent and the trigger element, couldn't I just change what triggers the animation? Which the more I type about it feels like it must just be the answer? But yeah, no structure talk so no worries if that's too much to get into! 😄
  3. I mean I could easily be wrong, but I didn't think I was asking about communicating up the react tree? I'd thought I was just asking about having a child component's gsap animation reference a parent - which may not work in React without passing refs, but it *does* work with Gsap, React and Astro. Maybe this is a side effect of SSR and astro rendering html prior to react components, and gsap *shouldn't* be able to select and use parent elements as triggers, but it seems to be able to. And that seemed linked to the idea that you scope your gsap selectors. I was just asking if it's ok to not scope the selectors and allow a child element to keep using the parent as a trigger - which it's currently doing I do understand about not talking about frameworks, but by avoiding talking about astro and react... I've got into a conversation about the best way to structure a framework that I'm not using? Just as a takeaway from this: Is it fair then to say that ScrollTrigger animations must be placed at *at least* the level of the component that contains the trigger? And I would've written it off as a bit of a curt and roundabout way of saying 'do more work' - which is fine, people need/deserve that sometimes when asking questions - if it wasn't in reply to a post where I outlined how and why I structured my app in the way I did, or for the other message that came off pretty condescending too. Hard for "you need to learn more" to come off as more than a skill issue in that context. Either way it doesn't really matter. Meant or not it was just a "let's stop" reply on my part and a brief explanation that I don't take this forum for granted. The replies annoyed me a bit, sure, but it's not a big deal.
  4. Hi Cassie, Sure, and I understand that, but I wasn't really asking for - and certainly wasn't expecting or felt entitled to - react tips or advice. Was just hoping someone could outline the downsides of not scoping useGSAP so that I could make design decisions based on the info available to me ::shrug::. If that's not possible or is particularly complicated to explain here to someone that doesn't understand that's (obviously) absolutely fine too. Appreciate the reply though, thanks
  5. Thanks @greenchonies. I was actually talking about the TS error (but maybe that's how you fixed it). Either way I got it sorted thanks. Cool animation btw, I forgot to mention at the time
  6. Not sure how this is related to be honest? I don't think having a reusable top level component is unusual in react, and flattening the structure at the top level seems like a weird thing to call out as a skill issue in a thread about scoping animations. But even if it was, this is quite a blunt way of responding to a post which essentially just asked about the downsides of not scoping an animation. And it followed an equally blunt reply mistakenly telling me not to comment in an additional topic, despite the comment coming before the topic itself. If I've done something to offend, or I've come across as a leech of the forum, let me know. I appreciate the work and help people give here and I'm aware that it's free - that's why I try to support the place with a premium subscription I've never used. I appreciate the help you've given me here and in the past too, but there's obviously an issue here, so probably best if we just leave it from now on. Thanks, Nick
  7. yeah, my <Section> components are just dumb reuseable components that accept params for styling and children, so i don't think that would be possible? my top level looks like this: <Section> <Hero /> <BlahBlah /> </Section> <Section> <Intro /> <BlahBlah /> </Section> tbh i like having a flattened structure like this - It's nice for layout/grid styling using tailwind arbitrary values. lets you see all the major element positions and the grids they sit in, at every breakpoint, in one relatively short file. it's also nice in terms of reuseability. I guess I'm asking how much more complex is it, so that I can balance that against other design considerations? If it's just a matter of having to be more specific with selectors, i'm ok with that.
  8. by 'keep everything inside the same component' do you mean the trigger/reference to '.section'? so i want to trigger animations using the elements themselves (or children), not anything higher in the DOM, right?
  9. but isn't that `useGSAP` code in the Box component? or am i then passing `section` to `Box`?
  10. Hi Rodrigo, I wrote this before I made that thread (but after the scoping one?), but I agree! Been enjoying the help (and useGSAP more generally tbh), thanks
  11. ok great, i'll have a read through that, thanks
  12. Thanks @Rodrigo - yeah normally I would've done, but I was following the docs I think? Isn't this the same as the example here: https://gsap.com/resources/React/ *edit: oh wait, mb, I was following the manual adding of listeners and forgot the cleanup fn being returned. i'll do it the other way const container = useRef(); const badRef = useRef(); const goodRef = useRef(); useGSAP((context, contextSafe) => { // ✅ safe, created during execution gsap.to(goodRef.current, {x: 100}); // ❌ DANGER! This animation is created in an event handler that executes AFTER useGSAP() executes. It's not added to the context so it won't get cleaned up (reverted). The event listener isn't removed in cleanup function below either, so it persists between component renders (bad). badRef.current.addEventListener("click", () => { gsap.to(badRef.current, {y: 100}); }); // ✅ safe, wrapped in contextSafe() function const onClickGood = contextSafe(() => { gsap.to(goodRef.current, {rotation: 180}); }); goodRef.current.addEventListener("click", onClickGood); // 👍 we remove the event listener in the cleanup function below. return () => { // <-- cleanup goodRef.current.removeEventListener("click", onClickGood); }; }, {scope: container}); return ( <div ref={container}> <button ref={badRef}></button> <button ref={goodRef}></button> </div> ); so this way instead const container = useRef(); const { contextSafe } = useGSAP({scope: container}); // we can pass in a config object as the 1st parameter to make scoping simple // ✅ wrapped in contextSafe() - animation will be cleaned up correctly // selector text is scoped properly to the container. const onClickGood = contextSafe(() => { gsap.to(".good", {rotation: 180}); }); return ( <div ref={container}> <button onClick={onClickGood} className="good"></button> </div> ); so useGSAP here takes an object instead of a function but returns a function that fulfils the same role? (allowing tls and animations to be added safely to the context?)
  13. Hi Rodrigo Yeah I saw that thanks (and I think the original thread linked above resulted in that recommendation by you too?) but I couldn't get it to work. It still seemed to complain that the safeContext function could be undefined. I probably did it wrong! See the Navigation component (line 15 and 27 of Navigation): https://stackblitz.com/edit/github-p21ql1?file=src%2Fcomponents%2FHeader.tsx,src%2Fpages%2Findex.astro,src%2Fcomponents%2FMobileBurger.tsx,src%2Fcomponents%2FNavigation.tsx,src%2Fcomponents%2FLogo.tsx Oh, and @Cassie here's the demo. Relevant bits in the Navigation component. Sorry it took so long!
  14. Yup I'll get on it now! Just thought it might be easy/obvious enough to not warrant one
  15. Similarly to the thread here I'm having problems typing my contextSafe function, but instead of getting “Type 'Function' is not assignable to type 'MouseEventHandler<HTMLDivElement>' I'm getting: Cannot invoke an object which is possibly 'undefined'.ts(2722) 'contextSafe' is possibly 'undefined'.ts(18048) const ref = useRef<HTMLDivElement>(null); useGSAP((context, contextSafe) => { const lines = gsap.utils.toArray<HTMLElement>(".line"); const burgerTl = gsap .timeline({ defaults: {duration:.4}, paused: true, }) .to(lines[0], { scaleX: 0 }) .to(lines[2], { scaleX: 0 }, '<.2') .to(lines[1], { rotate:135 }, '<.2') .set(lines[3], { display:'block', rotate:135}, '<.35') .to(lines[3], { rotate:45 }, '<'); const contextSafeClick = contextSafe(() => { // This call is the prob gsap.to(ref.current, {rotation: 180}); }); // ref.current.addEventListener("click", contextSafeClick); }); I can obviously make a guard condition (if(!contextSafe) return), but I thought it might be worth understanding why this is happening as I've not seen anyone else have to do this!
×
×
  • Create New...