Библиотека Muuri предоставляет мощный инструмент для организации динамических сеток с возможностью перетаскивания, фильтрации и анимации элементов. В контексте React важно учитывать особенности работы с виртуальным DOM, чтобы интеграция была эффективной и корректной.
Для начала необходимо установить библиотеку:
npm install muuri
или через Yarn:
yarn add muuri
Импорт в компонент React выглядит следующим образом:
import Muuri from 'muuri';
import { useEffect, useRef } from 'react';
Основной подход заключается в использовании useRef для
получения ссылки на контейнер сетки и useEffect для
инициализации Muuri после рендера.
Создание сетки выполняется в useEffect, чтобы
гарантировать наличие DOM-элементов:
const gridRef = useRef(null);
const muuriInstance = useRef(null);
useEffect(() => {
if (gridRef.current) {
muuriInstance.current = new Muuri(gridRef.current, {
dragEnabled: true,
layout: {
rounding: false
}
});
}
return () => {
if (muuriInstance.current) {
muuriInstance.current.destroy();
}
};
}, []);
Ключевые моменты:
gridRef обеспечивает доступ к DOM-контейнеру
сетки.muuriInstance хранит ссылку на объект Muuri для
дальнейших операций, таких как фильтрация или сортировка.return уничтожает экземпляр сетки при
размонтировании компонента, предотвращая утечки памяти.В React элементы часто управляются через состояние. Для синхронизации
с Muuri необходимо использовать методы add и
remove экземпляра сетки.
const [items, setItems] = useState([1, 2, 3]);
useEffect(() => {
if (muuriInstance.current) {
muuriInstance.current.add(items.map(item => {
const element = document.createElement('div');
element.className = 'item';
element.textContent = `Элемент ${item}`;
return element;
}));
}
}, [items]);
Удаление элементов производится с помощью метода
remove:
const removeItem = (index) => {
if (muuriInstance.current) {
const itemToRemove = muuriInstance.current.getItems()[index];
muuriInstance.current.remove(itemToRemove, { removeElements: true });
setItems(prev => prev.filter((_, i) => i !== index));
}
};
Особенности интеграции с React:
document.createElement или cloneNode.Muuri предоставляет удобные методы для сортировки и фильтрации:
// Фильтрация по чётным элементам
muuriInstance.current.filter(item => {
const value = parseInt(item.getElement().textContent.replace(/\D/g, ''), 10);
return value % 2 === 0;
});
// Сортировка по возрастанию
muuriInstance.current.sort((a, b) => {
const aValue = parseInt(a.getElement().textContent.replace(/\D/g, ''), 10);
const bValue = parseInt(b.getElement().textContent.replace(/\D/g, ''), 10);
return aValue - bValue;
});
Важно:
filter и sort автоматически
запускают анимацию, если она включена в настройках сетки.Drag-and-drop в Muuri работает независимо от React, но для корректного взаимодействия с состоянием рекомендуется отслеживать события Muuri:
useEffect(() => {
if (!muuriInstance.current) return;
const grid = muuriInstance.current;
grid.on('move', () => {
const newOrder = grid.getItems().map(item =>
parseInt(item.getElement().textContent.replace(/\D/g, ''), 10)
);
setItems(newOrder);
});
return () => grid.off('move');
}, []);
Ключевые моменты:
move позволяет обновлять React-состояние при
изменении порядка элементов.Muuri поддерживает плавные анимации при перемещении элементов, изменение их размеров и фильтрацию. В React важно отключать лишние перерендеры:
muuriInstance.current = new Muuri(gridRef.current, {
dragEnabled: true,
layout: {
fillGaps: true,
rounding: false,
horizontal: false
},
layoutOnInit: true,
dragContainer: document.body
});
Рекомендации для производительности:
requestAnimationFrame
совместно с Muuri.useRef и useEffect.componentDidMount, а уничтожается в
componentWillUnmount. Пример:componentDidMount() {
this.grid = new Muuri(this.gridRef, { dragEnabled: true });
}
componentWillUnmount() {
this.grid.destroy();
}
Такой подход обеспечивает корректную работу сетки в обоих типах компонентов, сохраняя совместимость с жизненным циклом React.
Эта интеграция позволяет создавать высоко динамические, интерактивные сетки в React с полным контролем над анимацией, сортировкой и перетаскиванием элементов, используя преимущества Muuri без нарушения принципов виртуального DOM.