Skip to content

React-хук ​

useMasonry(container, options?) — выход для случаев, когда render-prop раскладка <MasonryGrid> не подходит. Элементы карточек остаются полностью вашими — это только подключает движок к контейнеру и держит его в синхроне с options.items.

ts
function useMasonry(container: HTMLElement | null, options?: UseMasonryOptions): UseMasonryReturn

container и options сравниваются по ссылке, а не по содержимому — у ядра нет живого updateOptions(), поэтому смена ссылки пересоздаёт движок. Это реальное отличие от Vue-composable, который сравнивает options структурно и принимает реактивные ref/getter напрямую:

  • Передавайте стабильный container — из useState, а не из useRef (изменение значения обычного ref само по себе не вызывает ре-рендер, так что этот хук никогда не заметит, что элемент реально смонтировался).
  • Оборачивайте options в useMemo, если это ещё не константа уровня модуля — иначе свежий объект-литерал на каждый рендер будет пересоздавать движок буквально на каждом рендере.

Опции ​

UseMasonryOptions расширяет MasonryOptions (смотрите API движка) одним дополнительным полем:

items ​

UseMasonryItem[] · опционально

ts
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 не разрешится в реальный элемент.

Пример:

tsx
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>
  )
}