Other day me want create quick remove items from list animation for site. This time skip React Transition Group, try new View Transition, save time.
Why write lot code when few code do trick.
View Transition API Chrome only, but me no care.
Crux is document.startViewTransition
.
But need establish DOM before state, after state, but React.js donβt allow.
React.js reactive. Not synchronous. document.startViewTransition
need synchronous.
Ask Google learn:
import { flushSync } from "react-dom";
flushSync(() => setState(...));
Me write hook:
import { useEffect, useState } from "react";
import { flushSync } from "react-dom";
export const useViewTransition =
typeof document !== "undefined" && "startViewTransition" in document
? <T>(newValue: T) => {
const [value, setValue] = useState(newValue);
useEffect(() => {
if (value !== newValue)
document.startViewTransition(() => {
flushSync(() => {
setValue(newValue);
});
});
}, [newValue]);
return value;
}
: <T>(value: T) => value;
If use useQuery
const { data: newMsgs } = useQuery({
queryKey: ["msgs"],
queryFn: msgs.all(25)
});
const msgs = useViewTransition(newMsgs);
return (
<ol>
{msgs?.map(item => (
<li
key={item.id}
style={{
viewTransitionName: "msg-" + item.id,
viewTransitionClass: "mymsg",
}}
>
{item.title}
</li>
))}
</ol>
);
Now when useQuery
update, hook call document.startViewTransition
then setState
.
Need global CSS
Me add global.css
:
@supports (view-transition-name: none) {
::view-transition-group(root) {
animation-duration: 0s;
}
::view-transition-group(.mymsg) {
animation-duration: 0.4s;
}
}
This tell Chrome: donβt transition whole page, only transition list items.
Now message list animation work. Very nice.
Top comments (0)