React Hook
useMasonry(container, options?) — the low-level escape hatch for when <MasonryGrid>'s render-prop layout doesn't fit. You own the item elements yourself; this only wires the engine to a container and keeps it in sync with options.items.
function useMasonry(container: HTMLElement | null, options?: UseMasonryOptions): UseMasonryReturncontainer and options are compared by reference, not by content — core has no live updateOptions(), so a changed reference tears down and recreates the engine. This is a real difference from the Vue composable, which compares options structurally and accepts reactive refs/getters directly:
- Pass a stable
container— fromuseState, notuseRef(a plain ref's value change doesn't itself trigger a re-render, so this hook would never notice the element actually mounted). - Memoize
optionswithuseMemoif it isn't already a module-level constant — a fresh object literal on every render would otherwise tear the engine down and recreate it every single render.
Options
UseMasonryOptions extends MasonryOptions (see Engine API) with one extra field:
items
UseMasonryItem[] · optional
interface UseMasonryItem extends Omit<MasonryItemDescriptor, 'el'> {
el: HTMLElement | null | undefined
}el is a plain, already-resolved element or null/undefined — not a ref/getter like the Vue composable's equivalent. Drive it from your own state (e.g. a callback ref backed by useState): a plain useRef won't re-trigger this hook's effect when the element actually mounts, for the same by-reference-comparison reason container needs useState too. Items whose el is currently null/undefined are filtered out before being passed to the engine.
Return value
engine
MasonryEngine | null
The engine instance (see Engine API) — a plain value, not wrapped in anything reactive (React's own re-render is what keeps it current), null until container resolves to a real element.
Example:
import { useState, useMemo } from 'react'
import { useMasonry } from '@macrulez/masonry-kit-react'
function Board() {
const [containerNode, setContainerNode] = useState<HTMLElement | null>(null)
const [cardAEl, setCardAEl] = useState<HTMLElement | null>(null)
const [cardBEl, setCardBEl] = useState<HTMLElement | null>(null)
const options = useMemo(
() => ({
columns: 'auto' as const,
minLaneSize: 240,
items: [
{ id: 'a', el: cardAEl },
{ id: 'b', el: cardBEl, colSpan: 2 },
],
}),
[cardAEl, cardBEl],
)
const { engine } = useMasonry(containerNode, options)
return (
<div ref={setContainerNode}>
<div ref={setCardAEl}>A</div>
<div ref={setCardBEl}>B</div>
</div>
)
}