Good morning, I'm building this prototype of an Android application that should use the Autocomplete function of Here API to help select a location to search.
This are my code files:
App.js:
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View } from 'react-native';
import { Provider } from 'react-redux'
import { store } from './store';
import TabTwoScreens from './screens/TabTwoScreens';
export default function App() {
return (
<Provider store={store}>
<TabTwoScreens />
</Provider>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
TabTwoScreen (inside the screens folder):
import React, { useState } from 'react';
import { Text, View, SafeAreaView, StyleSheet, TouchableWithoutFeedback, Pressable, Keyboard, FlatList, TextInput } from "react-native";
import { Location } from "../types/location";
import { MaterialIcons } from "@expo/vector-icons"
export default function TabTwoScreeen() {
const [input, setInput] = useState<string>();
const [data, setData] = useState<Location[]>();
// updates the input
const onChangeText = async (text: string) => {
setInput(text)
if (text.length === 0) return setData([]);
if (text.length > 2) {
let endpoint = `http://192.168.0.105:4000/api/search?location=${text}&limit=${5}`
const res = await fetch(endpoint);
if (res) {
const data: Location[] = await res.json();
if (data.length > 0) setData(data);
}
}
console.log("get data")
}
const getItemText = (item: Location) => {
let mainText = item.title;
return (
<View style={{ flexDirection: "row", alignItems: "center", padding: 15 }} >
<MaterialIcons
name={item.administrativeAreaType === "city" ? "location-city" : "location-on"}
color={"black"}
size={30}
/>
<View style={{ marginLeft: 10, flexShrink: 1 }}>
<Text style={{ fontWeight: "700" }}>{mainText}</Text>
<Text style={{ fontSize: 12 }}>{item.address.countryName}</Text>
</View >
</View >
)
}
return (
<TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>
<SafeAreaView style={{ flex: 1 }}>
<View style={styles.container}>
<Text style={styles.label}>Search Location</Text>
<TextInput
placeholder="Find location"
value={input}
onChangeText={onChangeText}
style={styles.input}
/>
<FlatList
data={data}
renderItem={({ item, index }) => (
<Pressable onPress={() => alert("navigate passing" + JSON.stringify(item))}
>
</Pressable>
)}
/>
</View>
</SafeAreaView>
</TouchableWithoutFeedback>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: 50,
marginLeft: 12,
marginRight: 12,
},
label: {
marginBottom: 5,
fontSize: 12,
},
input: {
height: 40,
borderWidth: 1,
paddingHorizontal: 10,
borderRadius: 5,
},
});
The index.ts (inside src_mine folder):
import dotenv from "dotenv";
dotenv.config();
import express from "express";
import cors from "cors";
import helmet from "helmet";
import axios from "axios";
const app = express()
app.use(cors());
app.use(helmet());
app.get("api/search", async (req, res) => {
try {
const endpoint = `https://autocomplete.search.hereapi.com/v1/autocomplete?apikey=${process.env.HERE_key}&lang=it-IT&limit=${req.query.limit}&q=${req.query.location}`;
const { data } = await axios.get(endpoint);
if (data) return res.send(data);
res.send([]);
} catch (error) {
res.send([]);
}
});
app.use("/", (req, res) => {
res.send("Hello There");
})
const port = process.env.PORT || 4000;
app.listen(port, () => console.log("listening on", port))
and finally the location.ts (inside types folder):
export type Location = {
title: string;
id: string;
language: string;
resultType: string;
administrativeAreaType?: string;
localityType?: string;
address: {
label: string;
countryCode: string;
countryName: string;
stateCode?: string;
state?: string;
county?: string;
city?: string;
postalCode?: string;
};
highlights: {
title?: { start: number; end: number }[];
address?: {
label?: { start: number; end: number }[];
state?: { start: number; end: number }[];
city?: { start: number; end: number }[];
};
};
};
Using the expo start
command, i'm able to see on my phone the research tab and i can write into it.
Until I digit the first two characters, it goes all smooth, and I receive as response on the terminal 'get data'.
From the third digit going on, nothing happens anymore.
I'm not too expert in React native language, so i do not have a precise idea on how i can somehow debug the code.
My opinion is that there is an error due to the request to the API, or maybe on the server, but I'm not able to find it.
Anyone can help me?
In your TabTwoScreen component, you are checking if(res)
which becomes true for either success or failure of the API (See behavior of Fetch API here https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch). So it is most probably going inside the block and failing at await res.json()
.
You should read the res
object to see if it is as expected before proceeding further.
You can try following to get a better idea on how to fix the errors -