emmme Posted October 6, 2023 Share Posted October 6, 2023 Hi All! This codesandbox https://codesandbox.io/p/sandbox/nifty-voice-gnkw7w?file=%2Fsrc%2Findex.css%3A42%2C1 displays a simple Stars Background animation. Since i saw this old post talking about using a document's fragment in which to append all the stars, my question is: is it still the proper way to handle Performance, even with React ? Link to comment Share on other sites More sharing options...
Rodrigo Posted October 6, 2023 Share Posted October 6, 2023 Hi, When it comes to performance and optimization, there is an argument to be made about everything. Whether or not making such argument makes sense or is worth making it, that's an entirely different thing. When it comes to performance is always a good idea to test, test, test. If you see something that is not working then try a different approach. Blake's approach is great and should work really nice regardless of the UI framework you use (React, Vue, Svelte, Alpine, etc). Just be sure that you append the fragment to an element that will be removed when the route changes (the view is unmounted) or manually do so in the cleanup phase of the effect hooks. As for specific React performance issues, normally those could arise in this cases because you are tying something to the state in order to create the elements, updating some state property constantly (causing a bunch of re-renders). Other than that any performance problem will happen regardless of the framework (if you are using one). Is using a document fragment in React something that can be done? Sure why not. Again if you are careful about it it shouldn't cause any issues. Maybe some React purists will consider you a blasphemous, but those are React purists being React purists (see the first paragraph and instead of performance use react best practices) 🤷♂️ Finally you are using GSAP Context in your effect hook but you are not reverting it in the cleanup phase of your effect hook: useLayoutEffect(() => { const ctx = gsap.context(() => {}); return () => ctx.revert(); // <- easy cleanup! }, []); Take a look at the resources we have in this page: Hopefully this helps. Happy Tweening! 2 Link to comment Share on other sites More sharing options...
emmme Posted October 6, 2023 Author Share Posted October 6, 2023 @Rodrigo i forgot about reverting the context..! I have it in my VsCode snippet, must have written it by scratch and forgot.... 6 hours ago, Rodrigo said: but those are React purists being React purists (see the first paragraph and instead of performance use react best practices) 🤷♂️ haha indeed, call it in "NorthPolean" or call it in "SouthPolean" still ice it is I updated the codesanbox in order to include •Reverting •Fragment / adding each star to the fragment https://codesandbox.io/p/sandbox/nifty-voice-gnkw7w?file=%2Fsrc%2Fpages%2FHome%2Findex.jsx%3A15%2C20 but i can't make the stars appear... Link to comment Share on other sites More sharing options...
Rodrigo Posted October 11, 2023 Share Posted October 11, 2023 Hi, Sorry for the late response 🙏 The main issue is that you are adding your fragment and creating references to DOM nodes that are not yet rendered: var frag = document.createDocumentFragment(); var app = document.querySelector(".star-background"); var baseStar = document.querySelector(".star"); app.appendChild(frag); useLayoutEffect(() => {}, []); return ( // now the HTML is rendered ); So app and baseStar are both null because those elements are not rendered in the DOM yet, always do anything that has to do with selectors inside an effect hook: useLayoutEffect(() => { var frag = document.createDocumentFragment(); var app = document.querySelector(".star-background"); var baseStar = document.querySelector(".star"); app.appendChild(frag); }, []); return ( // now the HTML is rendered ); Now adding stuff using appendChild in React could backfire if you're not careful, is better to conditionally render the element based on some state condition that you can update in your initial render, like an effect hook with an empty dependencies array and then in another effect hook that checks for that specific state property. In any case this seems to work as you expect: useLayoutEffect(() => { // fragment var app = document.querySelector(".star-background"); var frag = document.createDocumentFragment(); // GSAP Context let ctx = gsap.context((self) => { //Starts building const stars = gsap.utils.toArray(".star"); stars.forEach((star) => { gsap.set(star, { x: () => Math.random() * window.innerWidth, y: () => Math.random() * window.innerHeight, }); gsap.to(star, { duration: 1, opacity: 1, stagger: 0.2, repeat: -1, yoyo: true, }); // Make the stars twinkle gsap.fromTo( star, { opacity: 0.5, scale: 0.5, }, { duration: 3.5, delay: Math.random() * 3, opacity: 1, scale: 1, repeat: -1, yoyo: true, stagger: 3.2, }, ); // add star to fragment frag.appendChild(star); app.appendChild(frag); }); }); return () => ctx.revert(); }, []); Hopefully this helps. Happy Tweening! 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