RORK LABEN
TOOLING — Rorkの開発者向けリポジトリが動き続けています。rork-xcodeが7月16日、rork-deviceが7月15日、rork-plistが7月13日に更新されましたOPUS46 — RorkでClaude Opus 4.6が稼働しています。Rork MaxはClaude Codeを土台にアプリを組み立てる設計ですSIM — ブラウザ上で動くクラウドのiOSシミュレータを備え、実機へのインストールは1クリック、App Storeへの提出は2クリックと案内されていますMAX — Rork MaxはReact Nativeではなく純粋なSwiftを出力します。iPhone・iPad・Apple Watch・Apple TV・Vision Pro、そしてiMessageまでが射程ですNATIVE — HealthKit、ARKitとLiDAR、NFC、Dynamic Island、Live Activities、Metalによる3D、Core MLのオンデバイス推論まで扱えますSEED — RorkはLeft Lane Capitalが主導する1,500万ドルのシードラウンドを実施し、Peak XVとa16z Speedrunが参加しましたTOOLING — Rorkの開発者向けリポジトリが動き続けています。rork-xcodeが7月16日、rork-deviceが7月15日、rork-plistが7月13日に更新されましたOPUS46 — RorkでClaude Opus 4.6が稼働しています。Rork MaxはClaude Codeを土台にアプリを組み立てる設計ですSIM — ブラウザ上で動くクラウドのiOSシミュレータを備え、実機へのインストールは1クリック、App Storeへの提出は2クリックと案内されていますMAX — Rork MaxはReact Nativeではなく純粋なSwiftを出力します。iPhone・iPad・Apple Watch・Apple TV・Vision Pro、そしてiMessageまでが射程ですNATIVE — HealthKit、ARKitとLiDAR、NFC、Dynamic Island、Live Activities、Metalによる3D、Core MLのオンデバイス推論まで扱えますSEED — RorkはLeft Lane Capitalが主導する1,500万ドルのシードラウンドを実施し、Peak XVとa16z Speedrunが参加しました
記事一覧/開発ツール
開発ツール/2026-04-26中級

Rork で Google Places API を使ったお店検索アプリを作る — 位置情報連携の実践ガイド

Rork と Google Places API を組み合わせて、現在地から近くのお店を検索・地図表示するアプリを作る方法を解説します。動作確認済みのコードとつまずきやすいポイントを丁寧に紹介します。

Google Places API位置情報3地図React Native209Expo149外部API2

Rork でアプリを作り始めると、いずれ「現在地から近くのお店を探せる機能が欲しい」という場面に出会います。

飲食店検索、観光スポット案内、近くのサービス一覧 — 位置情報とスポット検索を組み合わせたアイデアは豊富です。ただ、地図コンポーネントと外部 API を同時に動かすのは、初めてだと少し複雑に感じるかもしれません。

完成したコードはそのまま使えるよう、コメントと期待する動作も記載しています。

Google Cloud で API キーを用意する

まず Google Cloud Console から Places API を有効化し、API キーを取得します。

  1. Google Cloud Console にアクセスし、新しいプロジェクトを作成します
  2. 「API とサービス」→「ライブラリ」で「Places API」を検索して有効化します
  3. 「認証情報」から API キーを作成します。本番運用では、アプリのバンドル ID(iOS)またはパッケージ名(Android)で制限をかけることをおすすめします
# .env ファイルに追記(API キーはコードに直接書かない)
EXPO_PUBLIC_GOOGLE_PLACES_API_KEY=YOUR_GOOGLE_PLACES_API_KEY

EXPO_PUBLIC_ プレフィックスをつけると、React Native のコード内でそのまま process.env.EXPO_PUBLIC_GOOGLE_PLACES_API_KEY として参照できます。.gitignore.env を追加するのも忘れずに。

なお、API キーを取得しただけでは不十分で、Google Cloud の課金アカウントを有効化しておく必要があります。これを見落とすと、後述する REQUEST_DENIED エラーの原因になります。

Rork でプロジェクトを作成する

Rork Companion を起動し、以下のようなプロンプトで初期構成を生成します。

現在地を取得して、半径 500m 以内のカフェを検索し、
地図上にマーカーで表示するアプリを作ってください。
マーカーをタップすると店名と住所が表示される構成にしてください。
API 呼び出しには fetch を使い、状態管理は useState と useEffect で行ってください。

生成されたコードの中で最初に確認すべきは、expo-location が依存関係に含まれているかどうかです。位置情報の取得にはこのパッケージが必要で、OS のパーミッション処理も含まれています。

現在地の取得と周辺スポット検索を実装する

位置情報の取得と API 呼び出しをカスタムフックに分離すると、コンポーネント側がすっきりします。

import * as Location from 'expo-location';
import { useState, useEffect } from 'react';
 
type Place = {
  place_id: string;
  name: string;
  vicinity: string;
  geometry: {
    location: { lat: number; lng: number };
  };
};
 
export function useNearbyPlaces() {
  const [places, setPlaces] = useState<Place[]>([]);
  const [userLocation, setUserLocation] = useState<{ lat: number; lng: number } | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [loading, setLoading] = useState(true);
 
  useEffect(() => {
    (async () => {
      // パーミッションを要求する
      const { status } = await Location.requestForegroundPermissionsAsync();
      if (status !== 'granted') {
        setError('位置情報のアクセスが許可されていません');
        setLoading(false);
        return;
      }
 
      // 現在地を取得する
      const location = await Location.getCurrentPositionAsync({
        accuracy: Location.Accuracy.Balanced,
      });
      const { latitude: lat, longitude: lng } = location.coords;
      setUserLocation({ lat, lng });
 
      // Google Places API で周辺のカフェを検索する
      const apiKey = process.env.EXPO_PUBLIC_GOOGLE_PLACES_API_KEY;
      const radius = 500;
      const type = 'cafe';
      const url =
        `https://maps.googleapis.com/maps/api/place/nearbysearch/json` +
        `?location=${lat},${lng}&radius=${radius}&type=${type}&language=ja&key=${apiKey}`;
 
      const response = await fetch(url);
      if (!response.ok) {
        setError('スポット情報の取得に失敗しました');
        setLoading(false);
        return;
      }
 
      const data = await response.json();
      // 正常時: { results: [{ name, vicinity, geometry, ... }], status: "OK" }
      setPlaces(data.results ?? []);
      setLoading(false);
    })();
  }, []);
 
  return { places, userLocation, error, loading };
}

このフックはエラーハンドリングも含んでいます。パーミッション拒否・ネットワーク障害のどちらが起きても error に文字列がセットされ、コンポーネント側でユーザーに通知できます。

地図にマーカーを表示する

フックを使うと、マップコンポーネント自体はシンプルに保てます。

import MapView, { Marker, PROVIDER_GOOGLE } from 'react-native-maps';
import { View, Text, StyleSheet } from 'react-native';
import { useNearbyPlaces } from './useNearbyPlaces';
 
export default function NearbyPlacesMap() {
  const { places, userLocation, error, loading } = useNearbyPlaces();
 
  if (loading) return <Text style={styles.status}>現在地を取得中...</Text>;
  if (error) return <Text style={styles.status}>{error}</Text>;
  if (!userLocation) return null;
 
  return (
    <View style={styles.container}>
      <MapView
        style={styles.map}
        provider={PROVIDER_GOOGLE}
        initialRegion={{
          latitude: userLocation.lat,
          longitude: userLocation.lng,
          latitudeDelta: 0.01,
          longitudeDelta: 0.01,
        }}
        showsUserLocation
      >
        {places.map((place) => (
          <Marker
            key={place.place_id}
            coordinate={{
              latitude: place.geometry.location.lat,
              longitude: place.geometry.location.lng,
            }}
            title={place.name}
            description={place.vicinity}
          />
        ))}
      </MapView>
    </View>
  );
}
 
const styles = StyleSheet.create({
  container: { flex: 1 },
  map: { flex: 1 },
  status: { flex: 1, textAlign: 'center', marginTop: 100, fontSize: 16 },
});

期待する動作: 端末の現在地を中心に地図が表示され、500m 圏内のカフェが赤いピンでマーキングされます。ピンをタップすると店名と住所のポップアップが現れます。

実装でつまずきやすい2つのポイント

ZERO_RESULTS または REQUEST_DENIED が返ってくる場合: API キーの取得だけでは足りません。Google Cloud の課金アカウントが有効になっていないと、正しいキーを使っていてもリクエストが弾かれます。Google Cloud Console の「お支払い」から課金アカウントをリンクし、Places API が「有効」ステータスになっているかを確認してください。無料枠があるので実費が発生するわけではありませんが、アカウントの紐付けは必須です。

Android で地図が白紙になる場合: PROVIDER_GOOGLE を使った MapView は、Android では google-services.json がプロジェクトルートに存在していることが求められます。Rork でビルドする際にこのファイルが配置されていないと、エラーメッセージなしに白紙の画面が表示されます。iOS では同様の問題は起きにくいですが、Android 向けにビルドする場合は事前に確認しておくと安心です。

位置情報アプリの詳細な実装パターンについては、Rork の外部 API 連携ガイドも参考にしてみてください。地図以外の外部サービスとの連携にも応用できる考え方がまとまっています。

アプリをさらに発展させるアイデア

このチュートリアルで作った「近くのカフェを地図に表示するアプリ」は、そのままリリースできる MVP として使えます。次のステップとして試してみると面白いと思うものをいくつか挙げます。

カテゴリ切り替えボタン(カフェ/レストラン/コンビニ)を追加すると、汎用性が大幅に上がります。type パラメーターを変えるだけなので実装は簡単です。

お気に入り登録機能については、Supabase を使ったスポット共有アプリの実装例が参考になります。友人とリストを共有する機能も視野に入るかもしれません。

また、place_id を使って Places API の詳細エンドポイントを叩くと、写真・営業時間・評価・電話番号も取得できます。詳細画面まで作り込むと、リリースできるアプリに近づきます。

全体を振り返って

今日試してみるとしたら、まず Google Cloud Console で API キーを取得して課金アカウントをリンクし、このコードをそのまま Rork に貼り付けてみてください。実際に自分のいる場所の周辺にピンが立つ様子を見ると、次にやりたいことが自然と浮かんできます。

位置情報アプリは、使う人が「いまいる場所」を起点にするため、リアルな体験と直結します。ぜひ動かしてみてください。

シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

開発ツール2026-07-15
「、」が行頭に落ちた — Rork が組んだ名言カードと日本語の禁則処理
React Native の Text は日本語の行頭禁則を保証しません。実測した違反率、WORD JOINER による事前結合の実装、onTextLayout での自動監査、Rork Max(SwiftUI)との挙動差までまとめました。
開発ツール2026-07-10
React Compiler を Expo に入れて、手書き memo を 41 箇所消しました
Rork が生成した React Native 画面に React Compiler を導入し、再レンダリング回数を Profiler で実測しました。手書き memo/useCallback の削除判断、効かない箇所の見分け方、CI での回帰検知までをまとめています。
開発ツール2026-07-09
Amplitude のファネルが一晩で改善したように見えたとき — イベントのスキーマ崩れを自己監査で炙り出す運用メモ
Rork で作ったアプリの Amplitude ファネルで、課金転換率が8%から19%へ跳ね上がったのに売上が動かない。原因はプロパティ名の崩れによる二重計上でした。イベント契約と実行時バリデータで崩れを計測し、段階的に締め直した運用メモです。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →