How to implement Mapbox GL JS with a custom Gutenberg block in FSE?

Is the element referenced in useRef somehow not an actual HTMLElement instance?

No, it is.

But (as you’ve already known it), Mapbox GL JS (v2.15.0) requires that the container, when supplied as an element, be an instance of window.HTMLElement. ( note the window. which means the parent window )

And the thing is, on the FSE/Site editor page, the block’s editor script which initializes the Mapbox map is in the parent window, but then div#map is inside a child window which is an iframe named editor-canvas, hence:

  1. document.getElementById('map'), where document refers to window.document, returned a null.

  2. The map div is no longer an instance of window.HTMLElement and instead, it’s now an instance of the iframe’s contentWindow.HTMLElement. I.e.

    • mapContainer.current instanceof HTMLElement (which is the same as mapContainer.current instanceof window.HTMLElement) returns false.

    • mapContainer.current instanceof document.querySelector( 'iframe[name="editor-canvas"]' ).contentWindow.HTMLElement returns true.

So for the time being, as you commented, you would need to use SSR (i.e. server-side rendering) instead.

I’ve created a GitHub repo with a working example where my edit function returns an element with an iframe which renders the Mapbox map, as you could see below: (I used Firefox)

Preview image

And here’s my edit function: ( see full code here )

const Edit = ( { attributes, setAttributes } ) => {
    const { accessToken } = attributes;

    const mapContainer = useRef( null );

    const [ mapLoaded, setMapLoaded ] = useState( false );

    const onMapFrameLoad = () => {
        let map;

        // Note: getMap is defined on the SSR page. It's a custom function which
        // returns the Mapbox instance for the map initialized on that SSR page.
        try {
            map = mapContainer.current.contentWindow.getMap();
        } catch ( error ) {
            console.log( 'Error accessing the Mapbox\'s map instance!', error );
            return;
        }

        map.on( 'load', () => {
            setMapLoaded( true );
            console.log( 'map ready', map );
        } );
    };

    return (
        <div { ...useBlockProps() }>
            { /* In this demo, I'm deliberately not using <InspectorControls>. */ }
            <fieldset>
                <TextControl
                    label="Access Token"
                    value={ accessToken }
                    onChange={ ( value ) => setAttributes( { accessToken: value } ) }
                />
            </fieldset>

            { ( accessToken && ! mapLoaded ) && <i>Loading map..</i> }

            { accessToken && (
                <iframe
                    src={ ssrPageUrl( accessToken, 300 ) }
                    width="100%"
                    height="300"
                    style={ { border: 0, overflow: 'hidden' } }
                    id="map-frame"
                    onLoad={ onMapFrameLoad }
                    ref={ mapContainer }
                ></iframe>
            ) }
        </div>
    );
};

casinojojobetpulibet girişOnwin Güncel Giriştürkçe altyazılı pornocanlı bahis casinocanlı bahis casino siteleriOnwin Güncel Girişcasinoholiganbet girişholiganbet güncel giriş