Closed2
React + typescript + GoogleMapApi でInfoWindowの中にボタン作って、それ押したら店舗情報取得してuseStateに格納する
めちゃくちゃ沼った。
そのまま溺れて召されても良いかなとも思った。
でも何とかエラーなしで動くコードになった。
- InfoWindowの中のカスタマイズは普通にHTMLが組み込める
- コンポーネントを組み込見たいので import { renderToString } from "react-dom/server"を使う
- styled-componentsでCustomeButton的なbuttonを作成して組み込んだら表示はできた
- しかし、onClickが発動しない
- InfoWindow内は普通のコンポーネント内の要素ではなくなるためonClick()関数が呼ばれないらしい
- buttonにidつけて、document.getElementByIdで取得しようとしても無理
- 最終手段としてReactDOM.renderを使ってコンポーネントをねじ込んで成功
- しかしReact18からはcreateRootを使えと言われるので書き直す
- でもcreateRootはtypescriptにまだ適応してないらしいので、ReactDom.createRootを使用する
- document.getElementByIdじゃなくてuseRef使ってaddEventListener("click", みたいにしてクリック要素復活させた
- と思ったら、useRefからのClickイベント取得は必要なかった。ReactDom.createRootをちゃんと書けばいい話だった。直接DOM操作してるからそりゃそうか。最初にClick要素が無効になったのが衝撃的過ぎて混乱していた
- とにかく完成!
こんな感じ(一部抜粋)
const createMarker = (place: google.maps.places.PlaceResult) => {
if (!place.geometry || !place.geometry.location) return;
const marker = new google.maps.Marker({
map: Map,
position: place.geometry.location,
title: place.name,
label: place.name?.charAt(0),
optimized: false,
});
const storeFix = () => {
changeStoreSelect(place.name, id);
console.log("店名は" + place.name);
};
infoWindows[0] = new google.maps.InfoWindow();
// infoWindowのカスタマイズコンポーネント→これをcreateRoot使ってレンダリングする
const CustomInfoContent = () => (
<>
<HeadingText>{place.name}</HeadingText>
<Text>住所:{place.vicinity}</Text>
<DivBox>{place.photos && place.photos.length > 0 ? <ImageBox w={"auto"} h={"auto"} maxh={"150px"} src={place.photos[0].getUrl()} /> : null}</DivBox>
<CustomButton
onClick={() => {
storeFix();
}}
>
決定
</CustomButton>
</>
);
// createRoot使ってレンダリングする。最終的にinfoWindowContentをぶち込む
const infoWindowContent = document.createElement("div");
const root = createRoot(infoWindowContent);
root.render(<CustomInfoContent />);
//マーカーをクリックしたときの処理
google.maps.event.addListener(marker, "click", () => {
// 2つ目があったら2つ目は閉じる
if (infoWindows[1]) infoWindows[1].close();
// 2つ目が存在しなかったら何もせず終了
if (!infoWindows[0]) return;
infoWindows[0].close();
// ここでInfoWindowを呼び出す
infoWindows[0].setContent(infoWindowContent);
infoWindows[0].open(marker.getMap(), marker);
console.log(place);
});
};
このスクラップは2023/11/11にクローズされました