【React/Leaflet】没にしたL.Control用のコンポーネントの供養場

ネコニウム研究所

PCを利用したモノづくりに関連する情報や超個人的なナレッジを掲載するブログ

【React/Leaflet】没にしたL.Control用のコンポーネントの供養場

2023-11-1 | , , ,

react-leafletでマップ上にUIを表示したくてL.Control用のコンポーネントを作ったんだけども、いろいろ問題があったので没になったコンポーネントの供養。

概要

今回の記事では、react-leafletでマップ上にUIを表示したくて作ったんだけども没にしたL.Control用のコンポーネントを紹介(供養)する。

仕様書

環境

  • react 18.2.0
  • react-leaflet 4.2.1
  • typescript 5.2.2

手順書

コードはこんな感じ。

import React from "react";
import ReactDOM from 'react-dom/client';
import L from "leaflet";
import { useMap } from "react-leaflet";
import { ChakraProvider } from "@chakra-ui/react";

interface CustomControlProps {
    position?: L.ControlPosition;
    className?: string;
    children: React.ReactNode;
}

const CustomControl: React.FC<CustomControlProps> = ({ children, position, className }) => {
    const map = useMap();

    React.useEffect(() => {
        const customControl = new L.Control({ position: position });

        customControl.onAdd = function () {
            const div = L.DomUtil.create('div', className);
            const reactRoot = ReactDOM.createRoot(div);
            reactRoot.render({children});
            return div;
        };

        customControl.addTo(map);

        return () => {
            customControl.remove();
        };

    }, [map, children, position, className]);

    return null;
}

CustomControl.defaultProps = {
    position: "topright",
    className: ""
};

export default CustomControl;

Chakra UIを使いたい場合は下記のように{children}を再度<ChakraProvider>で囲む必要がある。(これをやっていいのかは怪しい気がする)

        customControl.onAdd = function () {
            const div = L.DomUtil.create('div', className);
            const reactRoot = ReactDOM.createRoot(div);
            reactRoot.render(<ChakraProvider>{children}</ChakraProvider>);
            return div;
        };

これでマップ上にUIを表示できるようにはなる。

没になった理由

んで、なんで没になったのかという理由をいくつか挙げる。

useEffect時の処理が重い

例えば、Propsの値が変更されたらUIの表示の仕方を調整したい場合、再レンダーされるのでUIがちらつく程には処理が遅い。
CSSでうまくやればこの問題は回避できるとは思うんんだけども、ReactでCSSを使わない縛りプレイしてる私には問題だ。

react-reduxが使えない

これが私にとって致命的。
Chakra UIを強引に使えるようにした感じでrenderProviderを追加しても使えない。Provider毎の管理になってるのでそりゃそうだ。
これもやり方次第では回避はできると思うんだけども、めんどいのでreact-reduxを使いたいんじゃ!

まとめ(感想文)

んでんで、結局どうしたのかというと

<MapContainer ...>
    <Box
        position="absolute"
        top="16px"
        left="16px"
        zIndex="1000"
        width="calc(100% - 32px)"
    >
        とんでもなく凄いUI
    </Box>
</MapContainer>

こんな感じでBoxposition="absolute"にして配置した。

私みたいになんでもかんでもChakra UIでなんとかしたい場合に使えるかもね!