React native dynamically pop and show map markers from server - google-maps

I need to get marker positions on map position change from the server and reflect this new marker positions on the map. If I put some markers in the state it shows the markers however it doesn't show any marker dynamically. I don't get any error or warnings on the console.
App.js
import React, { Component } from 'react';
import { Text, View, StyleSheet, Switch, Alert, AppRegistry } from 'react-native';
import MapView from 'react-native-maps';
import Fetchdata from './Fetchdata.js';
const styles = StyleSheet.create({
container: {
...StyleSheet.absoluteFillObject,
height: 400,
width: 400,
justifyContent: 'flex-end',
alignItems: 'center',
},
map: {
...StyleSheet.absoluteFillObject,
},
});
export default class MyScreen extends Component {
render() {
return (
<View style ={styles.container}>
<Fetchdata />
</View>
);
}
}
FetchData.js
import React, { Component } from 'react'
import { Text, View, StyleSheet, Switch, Alert, AppRegistry} from 'react-native'
import MapView, {Marker} from 'react-native-maps';
const styles = StyleSheet.create({
container: {
...StyleSheet.absoluteFillObject,
height: 400,
width: 400,
justifyContent: 'flex-end',
alignItems: 'center',
},
map: {
...StyleSheet.absoluteFillObject,
},
});
export default class Fetchdata extends Component {
constructor (props) {
super(props);
};
state = {
latitude: 40.3565,
longitude: 27.9774,
markers:[]
};
componentDidMount = () => {
navigator.geolocation.getCurrentPosition(
(position) => {
this.setState({
latitude: position.coords.latitude,
longitude: position.coords.longitude,
error: null,
});
},
(error) => this.setState({ error: error.message }),
{ enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 },
);
}
onRegionChange (region) {
return fetch('https://isg.info.tr/query_maps.php' + '?latitude=' + this.state.latitude + '&longitude=' + this.state.longitude , {method: 'GET'})
.then((response) => response.json())
.then((responseJson) => {
const newState = Object.assign({}, this.state);
newState.markers.latlng = responseJson;
newState.latitude = region.latitude;
newState.longitude = region.longitude;
this.setState(newState);
console.log(responseJson);
})
};
render() {
return (
<View style={styles.container}>
<MapView
style={styles.map}
region={{
latitude: this.state.latitude,
longitude: this.state.longitude,
latitudeDelta: 0.015,
longitudeDelta: 0.015,
}}
onRegionChangeComplete={this.onRegionChange.bind(this)}
>
{this.state.markers.map(marker => (
<Marker
coordinate={marker.latlng}
title={"marker.title"}
description={"marker.description"}
/>
))}
</MapView>
</View>
);
}
}
JSON File that is returned by the server
[{"latitude":"40.3565","longitude":"27.9774"},{"latitude":"40.3471","longitude":"27.9598"},{"latitude":"40","longitude":"27.9708"}]

There are a few things going on there that are a problem and should be giving you an error. The problem is that none of those are being triggered because you're using onRegionChangeComplete, but the correct property is just onRegionChange. The errors at that point may get you the rest of the way.
If you get to a point where you've gone through the errors and are still not sure where to go, feel free to ask for more clarification.

Related

How to fix React Native code to show two different flatlist (Json Api) in one screen and can use search feature

I want to create an application screen, in that screen it can show 2 flatlists from different api, I call it using a button.
For that process I was successful, but I want to add a search feature by reading every list that is called or active at that time, but this doesn't work. And if I take it also does not work. In this flatlist I also want to be able to move the detail pages.
This is for my college semester assignment.
import {
Box,
Text,
Image,
Heading,
Center,
ScrollView,
Spinner,
FlatList,
Pressable,
View,
HStack,
Button,
} from 'native-base';
import React, { Component } from 'react';
import { Dimensions, TouchableOpacity, StatusBar } from 'react-native';
import {LinearGradient} from 'expo-linear-gradient';
import { Ionicons, Entypo } from '#expo/vector-icons';
import { ListItem, SearchBar } from '#rneui/themed';
const windowWidth = Dimensions.get('window').width;
class Legal extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
isLoading: true,
categories: ['apps', 'products'],
contentSwitcher: false,
isFetching: false,
searchTxt: null,
error: null,
temp: [],
};
}
async getApps() {
try {
const response = await fetch(
'https://ojk-invest-api.vercel.app/api/apps'
);
const json = await response.json();
this.setState({ data: json.data.apps });
} catch (error) {
console.error(error);
} finally {
this.setState({ isLoading: false, contentSwitcher: false });
}
}
async getProducts() {
try {
const response = await fetch(
'https://ojk-invest-api.vercel.app/api/products'
);
const json = await response.json();
this.setState({ data: json.data.products, contentSwitcher: true });
} catch (error) {
console.error(error);
} finally {
this.setState({ isLoading: false });
}
}
setResult = (res) => {
this.setState ({
data: [...this.state.data, ...res.data.apps],
temp: [...this.state.temp, ...res.data.apps],
error: res.error || null,
isLoading: false,
});
};
renderHeader = () => {
return <SearchBar placeholder='Cari ...'
lightTheme round editable={true}
value={this.state.searchTxt}
onChangeText={this.updateSearch}
/>
};
updateSearch = searchTxt => {
this.setState({searchTxt}, () => {
if ('' == searchTxt) {
this.setState({
data: [...this.state.temp],
});
return;
}
this.state.data = this.state.temp.filter(function (item) {
return item.name.includes(searchTxt);
}).map(function({ id, name, type }) {
return {id, name, type};
});
});
};
componentDidMount() {
this.getApps();
}
onRefresh = () => {
this.setState({ isFetching: true }, () => {
this.getApps();
});
};
renderItem = ({ item }) => {
const { navigation } = this.props;
return (
<>
<Pressable
style={{ padding: 20, backgroundColor: 'white' }}
onPress={() => navigation.navigate('Detail Produk', { data: item })}>
<Center>
<View
style={{
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
}}>
<Text
style={{
fontSize: 16,
width: windowWidth - 40,
textAlign: 'justify',
marginTop: 6,
}}>
{item.name}
</Text>
<Text
style={{
color: '#808080',
fontSize: 14,
width: windowWidth - 40,
textAlign: 'justify',
marginTop: 6,
}}>
{this.state.contentSwitcher ? item.management : item.owner}
</Text>
</View>
</Center>
</Pressable>
<View style={{ borderWidth: 0.5, borderColor: '#cccccc' }}></View>
</>
);
};
render() {
const { data, isLoading, isFetching } = this.state;
return (
<View style={{ flex: 1, justifyContent: 'center'}}>
<HStack alignItems="center" bgColor="#fff" p="1" w={window.width}>
<Pressable m="2" rounded="8" p="2" flex={1} textAlign="center">
<Button onPress={() => this.getApps()}
leftIcon={<Ionicons name="folder" color="white" />}
colorScheme="green"
>
Aplikasi
</Button>
</Pressable>
<Pressable m="2" rounded="8" p="2" flex={1} textAlign="center">
<Button onPress={() => this.getProducts()}
leftIcon={<Entypo name="box" color="white" />}
colorScheme="green"
>
Produk
</Button>
</Pressable>
</HStack>
{isLoading ? (
<Spinner size="large" color="#AA0002" />
) : (
<FlatList
ListHeaderComponent={this.renderHeader}
data={data}
keyExtractor={({ link }, index) => link}
renderItem={this.renderItem}
onRefresh={this.onRefresh}
refreshing={isFetching}
/>
)}
</View>
);
}
}
export default Legal;

Invalid attempt to spread non-iterable instance. In order to be iterable, non-array objects must have a [Symbol.iterator]() method. in my app

i tried to show search result feature by using flatlist (json API) and search bar in my code, but i found this error and can't solve it. I can run the search but can't display the search results, can anyone help me solve this error, because this is for my college assignment
this is my code
import {
Box,
Text,
Image,
Heading,
Center,
ScrollView,
Spinner,
FlatList,
Pressable,
View,
Stack,
} from 'native-base';
import React, { Component } from 'react';
import { Dimensions } from 'react-native';
import { ListItem, SearchBar } from '#rneui/themed';
const windowWidth = Dimensions.get('window').width;
class Ilegal extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
isLoading: true,
isFetching: false,
searchTxt: null,
error: null,
temp: [],
};
};
async getData() {
try {
const response = await fetch(
'https://ojk-invest-api.vercel.app/api/illegals'
);
const json = await response.json();
this.setState({ data: json.data.illegals });
this.setResult(json);
} catch (error) {
console.error(error);
} finally {
this.setState({
isLoading: false,
isFetching: false,
});
}
};
setResult = (res) => {
this.setState ({
data: [...this.state.data, ...res],
temp: [...this.state.temp, ...res],
error: res.error || null,
isLoading: false,
});
};
renderHeader = () => {
return <SearchBar placeholder='Cari Perusahaan..'
lightTheme round editable={true}
value={this.state.searchTxt}
onChangeText={this.updateSearch}
/>
};
updateSearch = searchTxt => {
this.setState({searchTxt}, () => {
if ('' == searchTxt) {
this.setState({
data: [...this.state.temp],
});
return;
}
this.state.data = this.state.temp.filter(function (item) {
return item.name.includes(searchTxt);
}).map(function({ id, name, type }) {
return {id, name, type};
});
});
};
componentDidMount() {
this.getData();
};
onRefresh = () => {
this.setState({ isFetching: true }, () => {
this.getData();
});
};
renderItem = ({ item }) => {
const { navigation } = this.props;
return (
<>
<Pressable
style={{ padding: 20, backgroundColor: 'white' }}
onPress={() => navigation.navigate('Detail Ilegal', { data: item })}>
<Center>
<View
style={{
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
}}>
<Text
style={{
fontSize: 16,
width: windowWidth - 40,
textAlign: 'justify',
marginTop: 6,
}}>
{item.name}
</Text>
<Text
style={{
color: '#808080',
fontSize: 14,
width: windowWidth - 40,
textAlign: 'justify',
marginTop: 6,
}}>
{item.type}
</Text>
</View>
</Center>
</Pressable>
<View style={{ borderWidth: 0.5, borderColor: '#cccccc' }}></View>
</>
);
};
render() {
const { data, isLoading, isFetching, error} = this.state;
return (
<View style={{ flex:1, justifyContent:'center', backgroundColor:'white', flexDirection: 'column', }}>
{isLoading ? (
<Spinner size="large" color="#AA0002" />
) : (
<FlatList
ListHeaderComponent={this.renderHeader}
data={data}
keyExtractor={({ link }, index) => link}
renderItem={this.renderItem}
onRefresh={this.onRefresh}
refreshing={isFetching}
/>
)}
</View>
);
}
}
export default Ilegal;
you can help me for fixed this error ?
I think the error is in setResult() function as far as I could understood your set result function. You are setting data like this
this.setState({ data: json.data.illegals });
in getData() while you are fetching data from API but you are sending json as parameter to setResult which is object. Try to change your setResult() as below:
setResult = (res) => {
this.setState ({
data: [...this.state.data, ...res.data.illegals],
temp: [...this.state.temp, ...res.data.illegals],
error: res.error || null,
isLoading: false,
});
};

I have this issue undefined is not an object (evaluating 'this.state.dataSource.map')

I want to display a list of places from a online json url.
import React, { Component } from "react";
import {
View,
StyleSheet,
Dimensions,
Image,
StatusBar,
TextInput,
TouchableOpacity,
Text,
Button,
Platform,
Alert,
FlatList,
ActivityIndicator,
} from "react-native";
let url = "https://cz2006api.herokuapp.com/api/getAll";
let url2 = "";
export default class ClinicComponent extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: null,
};
}
componentDidMount() {
return fetch("https://cz2006api.herokuapp.com/api/getAll")
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson.data.data,
});
})
.catch((error) => {
console.log(error);
});
}
render() {
if (this.state.isLoading) {
return (
<View style={styles.container}>
<ActivityIndicator />
</View>
);
} else {
let hospitals = this.state.dataSource.map((val, key) => {
return (
<View key={key} style={styles.item}>
<Text>{val.name}</Text>
</View>
);
});
return (
<View style={styles.item}>
{/* <Text>Content Loaded</Text> */}
{hospitals}
</View>
);
}
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
item: {
flex: 1,
alignSelf: "stretch",
margin: 10,
alignItems: "center",
justifyContent: "center",
borderBottomWidth: 1,
borderBottomColor: "#eee",
},
});
Unfortunately when i tried to run this via expo cli I got an error, saying undefined is not an object
enter image description here
Can anyone help me pls!!! I would just like to have a list of hospitals which are scrollable. Thank you!
The URL of the Json is here: https://cz2006api.herokuapp.com/api/getAll
Simply change your initial state to something like this
this.state = {
isLoading: true,
dataSource: [], // <-- here
};
Your problem is you're using dataSource.map but during api calling your dataSource still stay null until it get its response, and null object have no attribute map. That's the cause of your problem.
remove the return in componentDidMount:
componentDidMount() {
fetch("https://cz2006api.herokuapp.com/api/getAll")
.then((response) => response.json())
.then((responseJson) => {
this.setState({
dataSource: responseJson.data.data,
isLoading: false,
});
})
.catch((error) => {
console.log(error);
});
}
I agree with #Nguyễn's suggestion that your initial state should be an array. However the root of the issue seems to be getting the right properties off off your JSON response.
First, you want responseJson.data instead of responseJson.data.data. That gives me an array and shows a long list but the titles are all blank. That's because your response has Name as an uppercase property but you are accessing name. So you need to change that as well.
export default class ClinicComponent extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: [],
};
}
componentDidMount() {
return fetch('https://cz2006api.herokuapp.com/api/getAll')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson.data,
});
})
.catch((error) => {
console.log(error);
});
}
render() {
//console.log(this.state.dataSource?.[0]);
if (this.state.isLoading) {
return (
<View style={styles.container}>
<ActivityIndicator />
</View>
);
} else {
return (
<View style={styles.item}>
{/* <Text>Content Loaded</Text> */}
{this.state.dataSource.map((val, key) => (
<View key={val._id} style={styles.item}>
<Text>{val.Name}</Text>
</View>
))}
</View>
);
}
}
}
You are fetching a huge amount of data and you probably want some sort of pagination with infinite scrolling. It is extremely slow to load due to the huge payload that we are fetching.
You also have double-escape problem in the JSON response inside the geocodingData section. You want to return this data as an object but it is an escaped string with lots of \" instead.

MQTT Response with React Native

I am currently making an IoT App that I'm trying to connect to a raspberry pi using MQTT. I use the react_native_mqtt package. I use the code posted by simaAttar from here: How to use MQTT on React Native? . The problem I have it doesnt always update my code when I alter it and save. What I'm trying to achieve is to receive a JSON formatted string from the rasp and use that to fill a FlatList with react-native-elements ListItem. But the data received is undefined, even though yesterday I did have it working for a second, it won't work anymore now.
Any help is appreciated.
EDIT: this is the code (forgot to post it)
import React, {Component} from 'react';
import init from 'react_native_mqtt';
import AsyncStorage from '#react-native-community/async-storage';
import {
ActivityIndicator,
StyleSheet,
Text,
View,
FlatList,
TouchableOpacity,
TextInput,
Button,
Alert,
} from 'react-native';
import {ListItem} from 'react-native-elements';
init({
size: 10000,
storageBackend: AsyncStorage,
enableCache: true,
sync: {},
});
export default class AllPeople extends Component {
constructor() {
super();
this.onMessageArrived = this.onMessageArrived.bind(this);
this.onConnectionLost = this.onConnectionLost.bind(this);
const client = new Paho.MQTT.Client(
'onto.mywire.org',
8080,
'Client-' + Math.random() * 9999 + 1,
);
client.onMessageArrived = this.onMessageArrived;
client.onConnectionLost = this.onConnectionLost;
client.connect({
onSuccess: this.onConnect,
useSSL: false,
onFailure: (e) => {
console.log('Error: ', e);
},
});
this.state = {
message: [''],
data: [],
isLoading: true,
client,
messageToSend: '',
isConnected: false,
};
}
onConnect = () => {
console.log('Connected');
const {client} = this.state;
client.subscribe('/app/to/allpeople');
this.setState({
isConnected: true,
error: '',
isLoading: true,
messageToSend: 'allpeople',
});
this.sendMessage();
};
onMessageArrived(entry) {
console.log("Nieuwe Test 1:")
console.log("PayloadMEssage: "+entry.payloadMessage);
console.log("Payload tostring: "+entry.payloadMessage.toString())
//this.setState({data: entry, isLoading: false});
}
sendMessage = () => {
console.log('message send.');
var message = new Paho.MQTT.Message(this.state.messageToSend);
message.destinationName = '/app/from';
if (this.state.isConnected) {
this.state.client.send(message);
} else {
this.connect(this.state.client)
.then(() => {
this.state.client.send(message);
this.setState({error: '', isConnected: true});
})
.catch((error) => {
console.log(error);
this.setState({error: error});
});
}
};
onConnectionLost(responseObject) {
if (responseObject.errorCode !== 0) {
console.log('onConnectionLost:' + responseObject.errorMessage);
this.setState({error: 'Lost Connection', isConnected: false});
}
}
render() {
return (
<View style={styles.container}>
{this.state.isLoading ? (
<ActivityIndicator />
) : (
<FlatList
keyExtractor={keyExtractor}
data={this.state.data}
renderItem={Item}
/>
)}
</View>
);
}
}
const keyExtractor = (item, index) => login.username.toString();
const Item = ({item}) => {
return (
<TouchableOpacity>
<ListItem
title="TestTitle" //{item.results.name.first}
titleStyle={{fontWeight: 'bold'}}
leftIcon={<MCIcons name="account" size={36} color="dodgerblue" />}
subtitle={item.results.name.last}
rightTitle={item.results.registered.date}
rightTitleStyle={{fontSize: 14}}
chevron
bottomDivider
/>
</TouchableOpacity>
);
};
const styles = StyleSheet.create({
container: {
backgroundColor: '#F5FCFF',
},
});
I have managed to fix it by changing entry.payloadMessage to entry.payloadString. Apparentyly I changed it during the editing of my code.

Trying to display JSON Data, but receiving JSON Parse Error

I am trying to display JSON data on my screen, the integer 4 to be exact.
But, I am receiving a JSON Parse Error.
I've posted and that works fine as in Webhooksite says it successfully posted. Also, it "gets" fine, but the data doesn't display. Please help!
// JSON Data
{
"cheetosamount": 4,
"cookiesvalue": 2
}
export default class ChooseDeliveries extends Component {
constructor(props){
super(props);
this.state = {
isLoading: true,
dataSource: null
}
}
componentDidMount(){
this.handleGetRequest();
}
handleGetRequest() {
fetch ('https://webhook.site/e61dd236-92d5-4b3b-882b-a50d6add6cd3',{
method: 'GET',
})
.then(response => response.json())
.then(responseJson => {
this.setState({
dataSource: JSON.parse(responseJson),
isLoading: false,
})
})
.catch(error => {
console.error(error);
});
};
render(){
if(this.state.isLoading){
return(
<View style={{flex: 1, padding: 20}}>
<ActivityIndicator/>
</View>
)
} else {
return(
<View style={{flex: 1, paddingTop:20}}>
<Text>
{this.state.dataSource.cheetosamount}
</Text>
</View>
);
}
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
I believe its because that 'JSON' that you are getting is already an object and there's no need for you to parse it.
More indepth explaination provided here SyntaxError: Unexpected token o in JSON at position 1
Try the following in your chrome console
let c ={
"cheetosamount": 4,
"cookiesvalue": 2
}
c.cheetosAmount
So essentially all you have to do is
this.setState({
dataSource: responseJson,
isLoading: false,
})