ReactでGoogleMapsAPIを使う（#3地図にカスタムコントロールを表示）

[前回記事](https://qiita.com/thebigeaterr/items/d7ff29fbe315f204a6e6)に引き続き、ReactでGoogleMapsAPIを触っていきます。
今回はカスタムコントロールを追加してみます。
地図の上部にInputボックスを入れるこんなやつを作ります。
<img width=400 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627012/7dee8b23-a4c7-4dbc-b76e-02b17ba62b8a.png" alt="2021-11-12 22.28.06.png">

### 前回作ったコンポーネントの確認
こんな感じでTest.jsとMap.jsを作ってました。
前回記事でMarkerコンポーネントを作っていますが、今回はここは無関係。

``` Test.js
import { Wrapper} from "@googlemaps/react-wrapper";
import Map from "./Map";
import Marker from "./Marker";

export default function Test(){

const positions =[
  {
          lat: 35.6809591,
          lng: 139.7673068,
      },
      {
          lat: 35.675069,
          lng: 139.763328,
      }
  ]

return (

<Wrapper apiKey={"ここにAPIkey"} >
  <MyMap>
  {positions.map(p=><Marker position={p}/>)}
  </MyMap>
</Wrapper>
)
}

```
``` Map.js
import React,{useRef,useEffect,useState} from 'react';

export default function Map({children}){
  const ref = useRef(null);
  const [map, setMap] = useState();

 useEffect(() => {
  if (ref.current && !map) {
    setMap(new window.google.maps.Map(ref.current, {
       center:{
          lat: 35.6809591,
          lng: 139.7673068,
      },
      zoom:14,
      mapTypeControl: false,
      streetViewControl: false,
      fullscreenControl: false,
    }));

  }
}, [ref, map]);

return(  <>
    <div ref={ref} style={{height:500, width:500}} />
    {React.Children.map(children, (child) => {
      if (React.isValidElement(child)) {
        return React.cloneElement(child, { map });
      }
    })}
  </>
  )
}

```
### SearchBoxコンポーネントを作る。
地図内の上部に表示する検索窓を作るため、コンポーネントを作ります。

```SearchBox.js
import React,{useRef,useEffect,useState} from 'react';

export default function SearchBox(props){
  const searchRef = useRef(null);
  
 useEffect(() => {
  if (props.map) {
      props.map.controls[google.maps.ControlPosition.TOP_CENTER].push(searchRef.current);
  }},[props.map])

return( 
     <input
      type="text"
      placeholder="ここに入力してください！"
      ref={searchRef}
      style={{
       border : "2px solid #fff",
       borderRadius : "3px",
       boxShadow : "0 2px 6px rgba(0,0,0,.3)",
       marginTop : "8px",
       textAlign:"center",
       width:400,
       height:40,
      }}
    />
  )
}

```
2点ほどポイントを説明すると、
#####親コンポーネント（Test.js）から子コンポーネント（Search.js）にmapインスタンスを渡す
[前回記事](https://qiita.com/thebigeaterr/items/d7ff29fbe315f204a6e6)でMarkerを追加した際にTest.jsは以下のように子コンポーネントにmapインスタンスを渡せるようにしました。

```Test.js
return(  <>
    <div ref={ref} style={{height:500, width:500}} />
    {React.Children.map(children, (child) => {
      if (React.isValidElement(child)) {
        return React.cloneElement(child, { map });
      }
    })}
  </>
  )

```
#### 上記により子コンポーネント（SearchBox）では受け取ったmapが使える。
SearchBoxコンポーネント内、useEffectを用いて以下を記載することで、地図内上部中央にカスタムコントロールを表示できます。

```SearchBox.js
 useEffect(() => {
  if (props.map) {
props.map.controls[google.maps.ControlPosition.TOP_CENTER].push(searchRef.current);
  }},[props.map])

```

### 親コンポーネントを書き換える。
SearchBoxを作ったので親コンポーネントである(Test.js)に追加します。

```
import { Wrapper} from "@googlemaps/react-wrapper";
import Map from "./Map";
import Marker from "./Marker";
import SearchBox from "./SearchBox";

export default function Test(){

const positions =[
  {
          lat: 35.6809591,
          lng: 139.7673068,
      },
      {
          lat: 35.675069,
          lng: 139.763328,
      }
  ]
      
return (
 <Wrapper apiKey={"ここにAPIキー"} >
   <Map>
   {positions.map((p,index)=><Marker position={p} key={index}/>)}
   <SearchBox/>
   </Map>
 </Wrapper>
)
}
```

###完成！
<img width=400 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627012/7dee8b23-a4c7-4dbc-b76e-02b17ba62b8a.png" alt="2021-11-12 22.28.06.png">