質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

React Native

React Nativeは、ネイティブモバイルアプリ(iOS/Android)を作成できるJavaScriptフレームワークです。Reactと同じ設計のため、宣言的なコンポーネントでリッチなUIを開発することが可能です。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

解決済

1回答

3469閲覧

ReactNative maximum call stack size exceeded の原因

rashild

総合スコア27

Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

React Native

React Nativeは、ネイティブモバイルアプリ(iOS/Android)を作成できるJavaScriptフレームワークです。Reactと同じ設計のため、宣言的なコンポーネントでリッチなUIを開発することが可能です。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

0クリップ

投稿2020/04/09 12:01

編集2020/04/09 12:09

ReactNativeでExpoを使ったアプリの開発をしています。
アプリの簡単な内容としてはアプリからユーザが位置情報を持った投稿をfirestoreに投稿し
他ユーザはマップの中心近くの投稿を検索することでMapViewにマーカーが立ち、投稿を見ることができるというものです。
エラー詳細は

Error

1RangeError:maximum call stack size exceeded 2This error is located at: 3in Image(at MapScreen.js) 4in AIRMapMarker(at MapMarker.js) 5in MapMarker(at MapScreen.js)

と出ているとおりImageコンポーネントでエラーが起きていると思っているのですが原因がわかりません。
RangeError:maximum call stack size exceeded というエラーからして再帰処理が起きていると思うのですが、どこで起きているのか分からず、疑い深い部分としてはsetStateすると再レンダリングがかかるらしく、stateが関係しているのではと思っています。

質問、お時間ある方よろしくお願いします。

追記(エラーが起きる動作を書いていませんでした)
アプリ起動時componentDidMountのgetLocationAsyncを呼び出し、getLocationAsync内のgetMusicで、そこから画面の中心近くの投稿をfirestoreから取得しmapにmarkerを表示するのですが、
Mapを動かして中心を変更した後、再検索しようと再度getMusic関数を呼び出すと上記のエラーが起きます。

MapScreen

1import React from "react"; 2import styled from "styled-components"; 3import { 4 View, 5 Text, 6 SafeAreaView, 7 StatusBar, 8 AsyncStorage, 9 Image, 10} from "react-native"; 11import { SearchBar } from "react-native-elements"; 12import MapView from "react-native-maps"; 13import { Callout, Marker } from "react-native-maps"; 14import * as Location from "expo-location"; 15import * as Permissions from "expo-permissions"; 16import { TouchableOpacity } from "react-native-gesture-handler"; 17import { Ionicons } from "@expo/vector-icons"; 18import { connect } from "react-redux"; 19import SoundLocation from "../components/Location"; 20import firebase from "../components/Firebase"; 21import { GeoFirestore } from "geofirestore"; 22 23function mapStateToProps(state) { 24 return { action: state.action }; 25} 26 27function mapDispatchToProps(dispatch) { 28 return {}; 29} 30 31const items = []; 32const firestore = firebase.firestore(); 33const geofirestore = new GeoFirestore(firestore); 34const geocollection = geofirestore.collection("posts"); 35 36class MapScreen extends React.Component { 37 static navigationOptions = { 38 header: null, 39 }; 40 41 constructor(props) { 42 super(props); 43 this.state = { 44 latitude: null, 45 longitude: null, 46 region: { 47 latitude: null, 48 longitude: null, 49 latitudeDelta: 0.02, 50 longitudeDelta: 0.02, 51 }, 52 firstQuery: "", 53 message: "位置情報取得中", 54 display: "none", 55 items: [], 56 }; 57 this.onRegionChangeComplete = this.onRegionChangeComplete.bind(this); 58 } 59 60 componentDidMount() { 61 StatusBar.setBarStyle("dark-content", true); 62 this.retrieveName(); 63 this.getLocationAsync(); 64 } 65 66 componentDidUpdate() { 67 68 } 69 70 retrieveName = async () => { 71 try { 72 const email = await AsyncStorage.getItem("email"); 73 if (email !== null) { 74 this.setState({ 75 display: "inline", 76 }); 77 } else { 78 this.setState({ 79 display: "none", 80 }); 81 } 82 } catch (error) {} 83 }; 84 85 getLocationAsync = async () => { 86 const { status } = await Permissions.askAsync(Permissions.LOCATION); 87 if (status !== "granted") { 88 this.setState({ 89 message: "位置情報のパーミッションの取得に失敗しました。", 90 }); 91 return; 92 } 93 let location = await Location.getCurrentPositionAsync({}); 94 var new_state = { 95 latitude: location.coords.latitude, 96 longitude: location.coords.longitude, 97 latitudeDelta: 0.02, 98 longitudeDelta: 0.02, 99 }; 100 this.setState({ 101 latitude: location.coords.latitude, 102 longitude: location.coords.longitude, 103 region: new_state, 104 }); 105 this.getMusic(); 106 }; 107 108 //検索 109 getMusic = function () { 110 const query = geocollection.near({ 111 center: new firebase.firestore.GeoPoint( 112 this.state.region.latitude, 113 this.state.region.longitude 114 ), 115 //delta * 100のあたい(緯度一度は約111kmらしい) 116 radius: this.state.region.latitudeDelta * 100, 117 }); 118 query.get().then((values) => { 119 items.length = 0; 120 values.docs.forEach(function (value, index) { 121 //itemsに格納する処理 122 console.log(value.data().title); 123 items.push({ 124 latitude: value.data().coordinates._lat, 125 longitude: value.data().coordinates._long, 126 icon: value.data().icon, 127 url: value.data().URL, 128 artist: value.data().artist, 129 title: value.data().title, 130 }); 131 }); 132 this.setState( 133 { 134 items: items, 135 }, 136 function () { 137 //console.log(this.state.items); 138 } 139 ); 140 }); 141 }; 142 143 getTest = () => { 144 //console.log(this.map.context); 145 this.map.animateToRegion( 146 { 147 latitude: this.state.latitude, 148 longitude: this.state.longitude, 149 latitudeDelta: 0.02, //小さくなるほどズーム 150 longitudeDelta: 0.02, 151 }, 152 1000 153 ); 154 }; 155 156 _onPressButton = async function (url) { 157 //省略 158 }; 159 160 onPlaybackStatusUpdate = (status) => { 161  //省略 162 }; 163 164 onRegionChangeComplete(region) { 165 var new_state = { 166 latitude: region.latitude, 167 longitude: region.longitude, 168 latitudeDelta: region.latitudeDelta, 169 longitudeDelta: region.longitudeDelta, 170 }; 171 this.setState({ 172 region: new_state, 173 }); 174 } 175 176 render() { 177 if (this.state.latitude && this.state.longitude) { 178 return ( 179 <RootView> 180 <View> 181 <SafeAreaView 182 style={{ 183 backgroundColor: "yellow", 184 display: "flex", 185 flexDirection: "row", 186 justifyContent: "space-between", 187 alignItems: "center", 188 }} 189 > 190 <SearchBar 191 round 192 onClearText={(text) => console.log(text)} 193 onChangeText={(query) => { 194 this.setState({ firstQuery: query }); 195 }} 196 returnKeyType="search" 197 value={this.state.firstQuery} 198 onEndEditing={() => console.log(this.state.firstQuery)} 199 containerStyle={{ 200 width: "80%", 201 borderRadius: 20, 202 marginBottom: 5, 203 marginLeft: 10, 204 }} 205 /> 206 <View 207 style={{ 208 flex: 1, 209 position: "absolute", 210 top: 50, 211 right: 20, 212 }} 213 > 214 <TouchableOpacity onPress={() => this.getMusic()}> 215 <Ionicons name="md-wifi" size={32} color="black" /> 216 </TouchableOpacity> 217 </View> 218 </SafeAreaView> 219 </View> 220 <MapView 221 ref={(map) => { 222 this.map = map; 223 }} 224 style={{ flex: 1 }} 225 initialRegion={{ 226 latitude: this.state.latitude, 227 longitude: this.state.longitude, 228 latitudeDelta: 0.02, //小さくなるほどズーム 229 longitudeDelta: 0.02, 230 }} 231 onRegionChangeComplete={(region) => 232 this.onRegionChangeComplete(region) 233 } 234 showsUserLocation={true} 235 showsMyLocationButton={true} 236 > 237 {this.state.items.map((item, index) => ( 238 <Marker 239 key={index} 240 coordinate={{ 241 latitude: item.latitude, 242 longitude: item.longitude, 243 }} 244 > 245 <Image 246 source={{ uri: item.icon }} 247 resizeMode="contain" 248 style={{ width: 44, height: 44 }} 249 /> 250 <Callout onPress={() => this._onPressButton(item.url)}> 251 <Location 252 key={index} 253 image={require("../assets/background.jpg")} 254 title={item.title} 255 artist={item.artist} 256 logo={{ uri: item.icon }} 257 author="author" 258 avatar={require("../assets/avatar.jpg")} 259 caption="caption" 260 /> 261 </Callout> 262 </Marker> 263 ))} 264 </MapView> 265 <View 266 style={{ 267 flex: 1, 268 position: "absolute", 269 bottom: 30, 270 left: 30, 271 }} 272 > 273 <TouchableOpacity onPress={() => this.getTest()}> 274 <Ionicons name="ios-navigate" size={48} color="black" /> 275 </TouchableOpacity> 276 </View> 277 <View 278 style={{ 279 flex: 1, 280 position: "absolute", 281 bottom: 30, 282 right: 30, 283 }} 284 > 285 <TouchableOpacity 286 onPress={() => { 287 this.props.navigation.push("Modal"); 288 }} 289 > 290 <Test source={require("../assets/avatar.jpg")} /> 291 </TouchableOpacity> 292 </View> 293 </RootView> 294 ); 295 } 296 return ( 297 <View style={{ flex: 1, justifyContent: "center" }}> 298 <Text>{this.state.message}</Text> 299 </View> 300 ); 301 } 302} 303 304export default connect(mapStateToProps, mapDispatchToProps)(MapScreen); 305 306const RootView = styled.View` 307 flex: 1; 308`; 309 310const Test = styled.Image` 311 width: 44px; 312 height: 44px; 313 background: black; 314 border-radius: 22px; 315 margin-left: 20px; 316`; 317

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

rashild

2020/04/10 15:06

今回の質問とは関係なさそうです。 エラー内容は変わっていませんでした。 ありがとうございます
guest

回答1

0

自己解決

すみません、自己解決しました。
FirestoreのGeoPointを手動で操作したせいで、GeoFirestoreが上手く動作していなかったようでデータを作り直したら正常に動作しました。
しかし、hoshi-takanoriさんの提案も起動時に何度も呼び出されている原因がわかっていなかったので大変助かりました。
ありがとうございました。

投稿2020/04/12 03:10

rashild

総合スコア27

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問