Next.js Discord

Discord Forum

Animation design patterns

Answered
Crazy ant posted this in #help-forum
Open in Discord
Crazy antOP
What is the common design pattern for implementing on load animations?

If I use framer motion is there a performance impact because I am changing from server components to client components, or does it just attach a bit of client side js.
Answered by alfonsüs ardani
first of all theres two types of "loading" animation in next.js due to added environments when developing full stack application.

first is the loading caused by streaming response, showing a placeholder htmls before JS fully received and loaded

second is the traditional, client-js-triggerd loading like setLoading and stuff (or from any state mgmt libraries that has loaders)

its important to note the constraint on the first one since its a html-only loading UI, you can't use any JS here and only rely on CSS animations/transitions to produce the loading animations. this is somewhat important since id assume that user will see this first on your web app if its not properly cached (to eliminate first access page load time)

however, you can freely use framer motion or any kind of web animations techniques (CSSAnimation, CSSTransition, WebAnimationAPI) for the second one as much as you want.

example scenario for number two is when user clicked something to trigger a client-side async UI state change that would need loading UI to await for the operation (like waiting for fetching new data or waiting for operation completion)
View full answer

22 Replies

It seems like it might not change much from what I’m reading online but ig that means I don’t understand the diff between client and server components
@Crazy ant What is the common design pattern for implementing on load animations? If I use framer motion is there a performance impact because I am changing from server components to client components, or does it just attach a bit of client side js.
first of all theres two types of "loading" animation in next.js due to added environments when developing full stack application.

first is the loading caused by streaming response, showing a placeholder htmls before JS fully received and loaded

second is the traditional, client-js-triggerd loading like setLoading and stuff (or from any state mgmt libraries that has loaders)

its important to note the constraint on the first one since its a html-only loading UI, you can't use any JS here and only rely on CSS animations/transitions to produce the loading animations. this is somewhat important since id assume that user will see this first on your web app if its not properly cached (to eliminate first access page load time)

however, you can freely use framer motion or any kind of web animations techniques (CSSAnimation, CSSTransition, WebAnimationAPI) for the second one as much as you want.

example scenario for number two is when user clicked something to trigger a client-side async UI state change that would need loading UI to await for the operation (like waiting for fetching new data or waiting for operation completion)
Answer
using framer motion or any kind of JS animations (including WAAPI) on the first case would not work at all since JS havent been loaded.
@Crazy ant I mean does it change what it pre-renders on the server?
It does not change what it pre-renders on the server as long as you dont "hide" the component on initial state of mount.

i.e you dont do this

const [visible, setVisible] = useState(false)
useEffect(setVisible(true), [])
return { visible ? <Content/> : null } // renders null on the server therefore wont appear on first page load even if it is later udpated


But as far as im concerned, when using the properties in framer motion, it only hides the component visual-wise and doesn't make it dissapear on first mount.
Its a common animation pattern to hide elements on first page load with CSS, and trigger animation when JS fully loads.
akin to something like this:


const contentRef = useRef<HTMLDivElement>(null)
useEffect(() => {
  contentRef.animate([
    // fade in
  ], {})
}, [])
return (<div className="invisible" ref={contentRef} />
but im sure framer-motion already handles that
@Crazy ant It seems like it might not change much from what I’m reading online but ig that means I don’t understand the diff between client and server components
think of client/server components as types of component syntax instead of a strict server-only or client-only component.

server components:
- runs in the server
- can't be run in the client
- can be async

client components:
- runs majority in client
- might run in server
- can't be async

Component definitions are by default gender-less/ambiguous and only becomes client-comp or server-comp based on where it is used
i think its good if u want animated skeletons
I lowkey have a slightly related question also
    useEffect(() => {
        if (view !== "remaining") return;

        const interval = setInterval(() => {
            setNow(Date.now())
        }, 33) 

        return () => clearInterval(interval)
    }, [view]);
so i have this thing that constantly updates the current date to compare against the time
which works fine
but my issue is i have a datepicker and the interval makes the interaction not work
if i remove it, the datepicker works fine but ig since its updating the page every 33 ms its interfering?
shadcn datepicker btw
Crazy antOP
alright i got it to work
i just used usememo and usecallback and made it child component since none of the props change
idk if thats the simplest way though?