не работает ymaps.templateLayoutFactory.createClass внутри меток Placemarker и Clusterer

Я нашел пример кода который отображает содержимое балунов с помощью компонентов. Захотел интегрировать в свой код, но я получаю ошибку. Я заметил, что если я не использую метки Placemarker и Clusterer и пишу ymaps.templateLayoutFactory.createClass где вызываю метод не из этих меток, то ошибка пропадает. Буду рад любой помощи. Спасибо.

Cannot read properties of undefined (reading 'createClass')
TypeError: Cannot read properties of undefined (reading 'createClass')

Пример кода

import React, { useState,useEffect } from 'react';
import { YMaps, Map, Clusterer , Button,Placemark } from 'react-yandex-maps';
import "../css/ballon.css"
import Header from "./Header";
import {Modal} from "react-bootstrap";
import InnerLayout from "./InnerLayout";
import ReactDOM from 'react-dom';
import ReactDOMServer from 'react-dom/server';
const mapState = {
    center: [55.7924886417031, 49.12233672582469],
    zoom: 9
};
import POINTS from './points';

const YMap = () => {

    const placemarkRef = React.useRef(null);
    const mapRef = React.useRef(null);
    const [address, SetAddress] = React.useState("");
    const [count, setValue] = useState(0);
    const [canAddPlacemark, checkAddPlacemark] = useState(false);
    const [oldRegionName, addOldRegionName] = useState();
    const [oldRegion, addOldRegion] = useState();
    const [ymaps, setYmaps] = useState(React.useRef(null));
    const [openedDescription, openDescription] = useState(null);
    const [clusterBalloon, setClusterBalloon] = useState(null);
    const [canAddMArker, checkAddMarker] = useState(false);

    const getLayout = (Component, props) => {
        if (ymaps) {
            const html = ReactDOMServer.renderToString(<Component {...props} />);
            const Layout = ymaps.templateLayoutFactory.createClass(`<div id="balloon">${html}</div>`,
                {
                    build: function() {
                        Layout.superclass.build.call(this);
                        ReactDOM.hydrate(
                            <Component {...props} />,
                            document.getElementById('balloon'),
                        );
                    },
                },
            );

            return Layout;
        }
        return null;
    };

    const animatedLayout = () => {
        if (ymaps) {
            const animatedLayout = ymaps.templateLayoutFactory.createClass(
                '<div class="placemark"></div>',
                {
                    build() {
                        animatedLayout.superclass.build.call(this);
                        const element = this.getParentElement().getElementsByClassName(
                            'placemark',
                        )[0];
                        const size = this.isActive ? 60 : 34;
                        const smallShape = {
                            type: 'Circle',
                            coordinates: [0, 0],
                            radius: size / 2,
                        };
                        const bigShape = {
                            type: 'Circle',
                            coordinates: [0, -30],
                            radius: size / 2,
                        };
                        this.getData().options.set(
                            'shape',
                            this.isActive ? bigShape : smallShape,
                        );
                        if (this.isActive) {
                            element.classList.add('active');
                            element.style.animation = '.35s show-big-placemark';
                        } else if (this.inited) {
                            element.classList.remove('active');
                            element.style.animation = '.35s show-small-placemark';
                        }
                        if (!this.inited) {
                            this.inited = true;
                            this.isActive = false;
                            this.getData().geoObject.events.add(
                                'click',
                                function() {
                                    this.isActive = !this.isActive;
                                    this.rebuild();
                                },
                                this,
                            );
                        }
                    },
                },
            );

            return animatedLayout;
        }
        return null;
    };

    useEffect(() => {
        if (document.getElementById('balloon') && clusterBalloon) {
            ReactDOM.hydrate(
                <InnerLayout
                    openDescription={openDescription}
                    openedDescription={openedDescription}
                    {...clusterBalloon}
                />,
                document.getElementById('balloon'),
            );
        }
    }, [clusterBalloon, openedDescription]);

    const openCluster = e => {
        const cluster = e.get('cluster');
        if (cluster) {
            if (!clusterBalloon) {
                setClusterBalloon(
                    cluster.state.get('activeObject').properties.getAll(),
                );
            }

            cluster.state.events.add('change', () => {
                const activeObject = cluster.state.get('activeObject');
                console.log(activeObject.properties.getAll().index)
                console.log(clusterBalloon.index)
                if (
                    !clusterBalloon ||
                    (clusterBalloon &&
                        activeObject.properties.getAll().index !== clusterBalloon.index)
                ) {
                    setClusterBalloon(activeObject.properties.getAll());
                }
            });
        }
    };

    const closeDescription = () => {
        setClusterBalloon(null);
        openDescription(null);
    };
    const createPlacemark = (coords) => {
        return new ymaps.current.Placemark(
            coords,
            {
                iconCaption: "loading.."
            },
            {
                preset: "islands#violetDotIconWithCaption",
                draggable: true
            }
        );
    };
    let regionName = "";
    const getAddress = async (coords) => {
        placemarkRef.current.properties.set("iconCaption", "loading..");
        await  ymaps.current.geocode(coords).then((res) => {
            const firstGeoObject = res.geoObjects.get(0);
            const newAddress = [
                firstGeoObject.getLocalities().length
                    ? firstGeoObject.getLocalities()
                    : firstGeoObject.getAdministrativeAreas(),
                firstGeoObject.getThoroughfare() || firstGeoObject.getPremise()
            ]
                .filter(Boolean)
                .join(", ");

            SetAddress(newAddress);

            placemarkRef.current.properties.set({
                iconCaption: newAddress,
                // balloonContentHeader: "одержимое заголовка балуна геообъекта",
                // balloonContentBody : "содержимое основой части балуна геообъекта",
                // balloonContentFooter : "содержимое нижней части балуна геообъекта.",
                // balloonContent: firstGeoObject.getAddressLine()
                balloonContent: '     <div> <input type="button" onClick={() => { openDescription(index);}} value="Подробнее"/> </div>'
            });
            regionName =firstGeoObject.getAdministrativeAreas()[0];
        })
    };
    
    const addMarkers = () =>{
            checkAddMarker(canAddMArker => !canAddMArker);
    }
    const onMapClick = (e) => {
        var objectId = e.get('id')
        console.log(objectId)
        if (canAddPlacemark){
            let objectManager = new ymaps.current.ObjectManager();
            objectManager.options.set('geoObjectInteractivityModel', 'default#transparent');
            const coords = e.get("coords");
            if (placemarkRef.current) {
                placemarkRef.current.geometry.setCoordinates(coords);
            } else {
                placemarkRef.current = createPlacemark(coords);
                mapRef.current.geoObjects.add(placemarkRef.current);
                placemarkRef.current.events.add("dragend", function () {
                    getAddress(placemarkRef.current.geometry.getCoordinates());
                });
            }
            getAddress(coords);
        }
    };

    function sayHello() {
        setValue(count+1);
        if(count % 2 != 0){
            checkAddPlacemark(canAddPlacemark => !canAddPlacemark)
        }
        else{
            checkAddPlacemark(canAddPlacemark => !canAddPlacemark)
        }

    }

    const handleClose2 = () => {
        setShow2(false);
    }
    const handleShow2 = () => {
        setShow2(true);
    }


    return (
        <div>
            <Header/>
            <YMaps query={{
                // load: "package.full" ,
                apikey: "" }}>
                <Map defaultState={{
                    center: [55.751574, 37.573856],
                    zoom: 9
                }}
                    modules={["Clusterer","Polygon","GeoObject","geoQuery","control.ZoomControl", "control.FullscreenControl","Placemark", "geocode",
                       "geoObject.addon.balloon","borders", "ObjectManager",'geoObject.addon.balloon','clusterer.addon.balloon',
                       'templateLayoutFactory']}
                     style={{
                         flex: 2,
                         height: "calc(100vh - 57px)"
                     }}
                     onClick={onMapClick}
                     instanceRef={mapRef}
                     onLoad={ymaps => setYmaps(ymaps)}
                     state={mapState}
                     width={"100%"} height={"100%"}
                >
                    <Clusterer
                        options={{
                            preset: 'islands#invertedVioletClusterIcons',
                            groupByCoordinates: false,
                            balloonPanelMaxMapArea: Infinity,
                            clusterBalloonItemContentLayout: getLayout(InnerLayout, {
                                openedDescription,
                                openDescription,
                                ...clusterBalloon,
                            }),
                        }}
                        onBalloonOpen={openCluster}
                        onBalloonClose={closeDescription}
                    >
                        {POINTS.map((point, index) => (
                            <Placemark
                                key={index}
                                geometry={point.coords}
                                properties={{
                                    balloonContentHeader: point.title,
                                    point,
                                    index,
                                }}
                                options={{
                                    iconLayout: animatedLayout(),
                                    balloonContentLayout: getLayout(InnerLayout, {
                                        point,
                                        index,
                                        openedDescription,
                                        openDescription,
                                    }),
                                    balloonPanelMaxMapArea: Infinity,
                                }}
                            />
                        ))}
                    </Clusterer>
                    <Button  onClick={sayHello} data={{ content: 'Button' }} options={{ float: 'right' }} />
                    <Button  onClick={addMarkers} data={{ content: 'Вывод маркеров' }} options={{ float: 'right' }} />
                    {/*{canAddMArker && <InnerLayout/>}*/}

                </Map>
            </YMaps>
        </div>

    )
}

export default YMap;

Ответы (0 шт):