LayoutGroup
Group motion components that should perform layout animations together.
By default, motion
components with a layout
prop will attempt to detect and animate layout changes every time they commit a React render.
It might be the case that components in different trees affect each other's layout.
function ToggleContent({ header, content }) { const [isOpen, setIsOpen] = useState(false) return ( <motion.div layout onClick={() => setIsOpen(!isOpen)} > <motion.h2 layout>{header}</motion.h2> {isOpen ? content : null} </motion.div> )}
function App() { return ( <> <ToggleContent /> <ToggleContent /> </> )}
When the state of one of these ToggleContent
components changes, its sibling won't rerender, so it won't perform a layout animation.
This can be fixed by grouping both components with LayoutGroup
:
import { LayoutGroup } from "framer-motion"
function App() { return ( <LayoutGroup> <ToggleContent /> <ToggleContent /> </LayoutGroup> )}
Now, whenever one layout
component within LayoutGroup
detects and animates layout changes, they all do.
#Namespace layoutId
Components expecting to perform shared layout animations are provided a layoutId
prop.
function Tab({ label, isSelected }) { return ( <li> {label} {isSelected ? <motion.div layoutId="underline" /> : null} </li> )}
function TabRow({ items }) { return items.map(item => <Tab {...item} />)}
layoutId
is global, so if multiple instances of TabRow
are rendered, only one with layoutId="underline"
will render at a time.
To fix this, LayoutGroup
can be provided an id
prop that namespaces the layoutId
for all components within it.
function App() { return ( <LayoutGroup id="top5"> <TabRow /> </LayoutGroup> <LayoutGroup id="latest"> <TabRow /> </LayoutGroup> )}