React-хук
useMasonry(container, options?) — выход для случаев, когда render-prop раскладка <MasonryGrid> не подходит. Элементы карточек остаются полностью вашими — это только подключает движок к контейнеру и держит его в синхроне с options.items.
function useMasonry(container: HTMLElement | null, options?: UseMasonryOptions): UseMasonryReturncontainer и options сравниваются по ссылке, а не по содержимому — у ядра нет живого updateOptions(), поэтому смена ссылки пересоздаёт движок. Это реальное отличие от Vue-composable, который сравнивает options структурно и принимает реактивные ref/getter напрямую:
- Передавайте стабильный
container— изuseState, а не изuseRef(изменение значения обычного ref само по себе не вызывает ре-рендер, так что этот хук никогда не заметит, что элемент реально смонтировался). - Оборачивайте
optionsвuseMemo, если это ещё не константа уровня модуля — иначе свежий объект-литерал на каждый рендер будет пересоздавать движок буквально на каждом рендере.
Опции
UseMasonryOptions расширяет MasonryOptions (смотрите API движка) одним дополнительным полем:
items
UseMasonryItem[] · опционально
interface UseMasonryItem extends Omit<MasonryItemDescriptor, 'el'> {
el: HTMLElement | null | undefined
}el — обычный, уже разрешённый элемент или null/undefined, а не ref/getter, как у эквивалента в Vue-composable. Управляйте им через собственное состояние (например, callback-ref на useState): обычный useRef не вызовет повторное срабатывание эффекта этого хука, когда элемент реально смонтируется — по той же причине сравнения по ссылке, из-за которой и container нужен useState. Карточки, у которых el сейчас null/undefined, отфильтровываются перед передачей движку.
Возвращаемое значение
engine
MasonryEngine | null
Инстанс движка (смотрите API движка) — обычное значение, не обёрнутое ни во что реактивное (актуальность поддерживает собственный ре-рендер React), null до тех пор, пока container не разрешится в реальный элемент.
Пример:
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>
)
}