使用HERE API的自动完成功能,React Native应用程序

huangapple go评论84阅读模式
英文:

Autocomplete with HERE api, React native application

问题

上午好,
我正在构建这个Android应用程序的原型,该应用程序应该使用Here API的自动完成功能来帮助选择要搜索的位置。

这是我的代码文件:

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(位于screens文件夹内):

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[]>();

    // 更新输入
    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("获取数据")
    }

    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}>搜索位置</Text>
                    <TextInput
                        placeholder="查找位置"
                        value={input}
                        onChangeText={onChangeText}
                        style={styles.input}
                    />
                    <FlatList
                        data={data}
                        renderItem={({ item, index }) => (
                            <Pressable onPress={() => alert("导航传递" + 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,
    },
});

index.ts(位于src_mine文件夹内):

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("你好");
})

const port = process.env.PORT || 4000;
app.listen(port, () => console.log("监听端口", port))

最后是location.ts(位于types文件夹内):

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 }[];
      };
    };
  };

使用expo start命令,我能在我的手机上看到搜索选项卡,并且可以在其中输入文字。在输入前两个字符之前,一切都很顺利,并且在终端上收到“获取数据”的响应。从第三个字符开始,再也没有发生任何事情。我对React Native语言不太熟悉,所以对于如何调试代码没有明确的想法。我认为问题可能出在对API的请求上,或者可能是服务器上的错误,但我无法找到它。有人可以帮我吗?

英文:

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 &#39;expo-status-bar&#39;;
import { StyleSheet, Text, View } from &#39;react-native&#39;;
import { Provider } from &#39;react-redux&#39;
import { store } from &#39;./store&#39;;
import TabTwoScreens from &#39;./screens/TabTwoScreens&#39;;
export default function App() {
return (
&lt;Provider store={store}&gt;
&lt;TabTwoScreens /&gt;
&lt;/Provider&gt;
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: &#39;#fff&#39;,
alignItems: &#39;center&#39;,
justifyContent: &#39;center&#39;,
},
});

TabTwoScreen (inside the screens folder):

import React, { useState } from &#39;react&#39;;
import { Text, View, SafeAreaView, StyleSheet, TouchableWithoutFeedback, Pressable, Keyboard, FlatList, TextInput } from &quot;react-native&quot;;
import { Location } from &quot;../types/location&quot;;
import { MaterialIcons } from &quot;@expo/vector-icons&quot;
export default function TabTwoScreeen() {
const [input, setInput] = useState&lt;string&gt;();
const [data, setData] = useState&lt;Location[]&gt;();
// updates the input
const onChangeText = async (text: string) =&gt; {
setInput(text)
if (text.length === 0) return setData([]);
if (text.length &gt; 2) {
let endpoint = `http://192.168.0.105:4000/api/search?location=${text}&amp;limit=${5}`
const res = await fetch(endpoint);
if (res) {
const data: Location[] = await res.json();
if (data.length &gt; 0) setData(data);
}
}
console.log(&quot;get data&quot;)
}
const getItemText = (item: Location) =&gt; {
let mainText = item.title;
return (
&lt;View style={{ flexDirection: &quot;row&quot;, alignItems: &quot;center&quot;, padding: 15 }} &gt;
&lt;MaterialIcons
name={item.administrativeAreaType === &quot;city&quot; ? &quot;location-city&quot; : &quot;location-on&quot;}
color={&quot;black&quot;}
size={30}
/&gt;
&lt;View style={{ marginLeft: 10, flexShrink: 1 }}&gt;
&lt;Text style={{ fontWeight: &quot;700&quot; }}&gt;{mainText}&lt;/Text&gt;
&lt;Text style={{ fontSize: 12 }}&gt;{item.address.countryName}&lt;/Text&gt;
&lt;/View &gt;
&lt;/View &gt;
)
}
return (
&lt;TouchableWithoutFeedback onPress={() =&gt; Keyboard.dismiss()}&gt;
&lt;SafeAreaView style={{ flex: 1 }}&gt;
&lt;View style={styles.container}&gt;
&lt;Text style={styles.label}&gt;Search Location&lt;/Text&gt;
&lt;TextInput
placeholder=&quot;Find location&quot;
value={input}
onChangeText={onChangeText}
style={styles.input}
/&gt;
&lt;FlatList
data={data}
renderItem={({ item, index }) =&gt; (
&lt;Pressable onPress={() =&gt; alert(&quot;navigate passing&quot; + JSON.stringify(item))}
&gt;
&lt;/Pressable&gt;
)}
/&gt;
&lt;/View&gt;
&lt;/SafeAreaView&gt;
&lt;/TouchableWithoutFeedback&gt;
);
}
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 &quot;dotenv&quot;;
dotenv.config();
import express from &quot;express&quot;;
import cors from &quot;cors&quot;;
import helmet from &quot;helmet&quot;;
import axios from &quot;axios&quot;;
const app = express()
app.use(cors());
app.use(helmet());
app.get(&quot;api/search&quot;, async (req, res) =&gt; {
try {
const endpoint = `https://autocomplete.search.hereapi.com/v1/autocomplete?apikey=${process.env.HERE_key}&amp;lang=it-IT&amp;limit=${req.query.limit}&amp;q=${req.query.location}`;
const { data } = await axios.get(endpoint);
if (data) return res.send(data);
res.send([]);
} catch (error) {
res.send([]);
}
});
app.use(&quot;/&quot;, (req, res) =&gt; {
res.send(&quot;Hello There&quot;);
})
const port = process.env.PORT || 4000;
app.listen(port, () =&gt; console.log(&quot;listening on&quot;, 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?

答案1

得分: 1

在你的 TabTwoScreen 组件中,你正在检查 if(res),它在 API 成功或失败时都会变为 true(请参考 Fetch API 的行为 https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)。所以很可能是进入了这个代码块,然后在 await res.json() 处失败了。
在继续之前,你应该查看 res 对象是否符合预期。

你可以尝试以下方法来更好地理解如何修复错误:

  1. 你可以使用浏览器来调试 React Native 应用程序,如此处所述 https://reactnative.dev/docs/debugging
  2. 这是另一个出色的包,它显示 API 调用并允许调试代码 https://github.com/jhen0409/react-native-debugger
英文:

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 -

  1. You can use your browser to debug the react native application as explained here https://reactnative.dev/docs/debugging
  2. This is another excellent package which shows API calls and allows debugging the code https://github.com/jhen0409/react-native-debugger

huangapple
  • 本文由 发表于 2023年6月13日 05:42:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/76460501.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定