使用 React Native 为 Zomato 创建搜索功能 API
Creating Search function with React Native for Zomato API
我不熟悉将 APIs 与 React Native 结合使用,我已经弄明白了一些事情,但我现在想做的是创建一个搜索功能。到目前为止,我已经尝试了一些方法,但要么函数没有被调用,要么我得到一个关于函数被作为对象调用的错误。此外,我正在使用 axios 进行此 API 调用
这是我目前所知道的。
export default class CategoryScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
isVisible: true,
city: '280',
isLoading: true,
search: ''
}
}
async componentDidMount() {
try {
const id = this.props.navigation.state.params.category;
const city = this.state.city;
const result = await axios.request({
method: 'get',
url: `https://developers.zomato.com/api/v2.1/search?city_id=${city}&category=${id}`,
headers: {
'Content-Type': 'application/json',
'user-key': 'a31bd76da32396a27b6906bf0ca707a2'
}
});
this.setState({ data: result.data.restaurants });
} catch (err) {
console.log(err);
} finally {
this.setState({ isLoading: false });
}
}
updateSearch = search => {
this.setState({ search });
};
searchReq = () => {
axios.request({
method: 'get',
url: `https://developers.zomato.com/api/v2.1/search?city_id=${city}&q${search}&category=${id}`,
header: {
'Content-Type': 'application/json',
'user-key': 'a31bd76da32396a27b6906bf0ca707a2'
}
});
this.setState({ data: result.data.restaurants });
}
render() {
const { search } = this.state;
return (
<SearchBar
placeholder="Type Here..."
onChangeText={this.updateSearch}
onSubmitEditing={this.searchReq}
value={search}
/>
)
}
}
如果有更高级的方法,我愿意学习新东西,我只想完成我想做的事情。此外,我知道如果我当前的方法有效,如果用户在两者之间添加 space 仍然会导致问题,所以我非常愿意学习新的和更高级的方法来做到这一点
我注意到你的搜索功能有几个错误。
- 您需要获取
city
、search
和 id
值,这些值不在 searchReq()
中
- 您需要先获取
result.data.restaurants
值,然后才能将其分配给 data: result.data.restaurants
因为你已经分配了 this.setState({ search })
我在 searchReq()
中得到了那个值,如下所示,
searchReq = async () => {
try {
const result = await axios.request({
method: 'get',
url: `https://developers.zomato.com/api/v2.1/search?city_id=280&q${this.state.search}&category=11`,
headers: {
'Content-Type': 'application/json',
'user-key': 'a31bd76da32396a27b6906bf0ca707a2'
}
});
this.setState({ data: result.data.restaurants });
} catch (error) {
this.setState({ data: [] });
console.log(error);
}
}
所以完整的源码是这样的
import React, { Component } from 'react';
import {
View,
Text,
FlatList,
StyleSheet,
TouchableOpacity,
Dimensions,
ActivityIndicator,
} from 'react-native';
import { Card, Image, SearchBar, Icon } from 'react-native-elements';
import Logo from '../assets/Logo.png'
import axios from 'axios';
const SCREEN_WIDTH = Dimensions.get('window').width;
const SCREEN_HEIGHT = Dimensions.get('window').height;
export default class CategoryScreen extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
isVisible: true,
city: '280',
isLoading: true,
search: ''
}
}
async componentDidMount() {
try {
const result = await axios.request({
method: 'get',
url: `https://developers.zomato.com/api/v2.1/search?city_id=280&category=11`,
headers: {
'Content-Type': 'application/json',
'user-key': 'a31bd76da32396a27b6906bf0ca707a2'
}
});
this.setState({
data: result.data.restaurants,
isLoading: false
});
} catch (err) {
this.setState({ isLoading: false });
console.log(err);
}
}
updateSearch = search => {
this.setState({ search });
};
searchReq = async () => {
try {
const result = await axios.request({
method: 'get',
url: `https://developers.zomato.com/api/v2.1/search?city_id=280&q${this.state.search}&category=11`,
headers: {
'Content-Type': 'application/json',
'user-key': 'a31bd76da32396a27b6906bf0ca707a2'
}
});
this.setState({ data: result.data.restaurants });
} catch (error) {
this.setState({ data: [] });
console.log(error);
}
}
render() {
const { search } = this.state;
return (
<View>
<View style={styles.header}>
<Image source={Logo} style={{ resizeMode: 'stretch', width: 50, height: 50, alignSelf: 'center', justifyContent: 'center', marginTop: 30 }} />
<Icon
raised
name='location'
type='octicon'
color='#f50'
onPress={() => this.setState({ isModalVisible: !this.state.isModalVisible })}
containerStyle={{ alignSelf: 'flex-end', marginRight: 20, marginTop: -60 }} />
</View>
<SearchBar
placeholder="Type Here..."
onChangeText={this.updateSearch}
onSubmitEditing={this.searchReq}
value={search}
inputStyle={{ backgroundColor: 'steelblue', color: 'white' }}
inputContainerStyle={{ backgroundColor: 'steelblue', fontColor: 'white' }}
containerStyle={{ backgroundColor: 'steelblue', borderBottomColor: 'transparent', borderTopColor: 'transparent' }}
placeholderTextColor='white'
/>
{
this.state.isLoading ?
<View style={{ flex: 1, marginTop: 200 }}>
<ActivityIndicator style={{ color: 'red' }} />
</View> :
(
this.state.data.length == 0 ?
<View style={{ flex: 1, padding: 20, marginTop: 100 }}>
<Text style={{ color: '#000', fontWeight: 'bold' }}>No restaurants from selected category</Text>
</View> :
<View style={{ flexDirection: 'column' }}>
<FlatList
keyExtractor={item => item.id}
data={this.state.data}
renderItem={({ item }) =>
<TouchableOpacity onPress={() => console.log(item.restaurant.location.city)}>
<Card style={{ width: SCREEN_WIDTH }}>
<Image style={{ width: SCREEN_WIDTH / 3, height: 130 }} resizeMode="stretch" source={{ uri: item.restaurant.thumb }} />
<Text style={{ color: '#000', fontWeight: 'bold' }}>{item.restaurant.name} </Text>
</Card>
</TouchableOpacity>
}
/>
</View>
)
}
</View>
)
}
}
const styles = StyleSheet.create({
header: {
backgroundColor: '#ff4714',
height: SCREEN_HEIGHT / 8,
},
});
希望对您有所帮助。
我不熟悉将 APIs 与 React Native 结合使用,我已经弄明白了一些事情,但我现在想做的是创建一个搜索功能。到目前为止,我已经尝试了一些方法,但要么函数没有被调用,要么我得到一个关于函数被作为对象调用的错误。此外,我正在使用 axios 进行此 API 调用
这是我目前所知道的。
export default class CategoryScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
isVisible: true,
city: '280',
isLoading: true,
search: ''
}
}
async componentDidMount() {
try {
const id = this.props.navigation.state.params.category;
const city = this.state.city;
const result = await axios.request({
method: 'get',
url: `https://developers.zomato.com/api/v2.1/search?city_id=${city}&category=${id}`,
headers: {
'Content-Type': 'application/json',
'user-key': 'a31bd76da32396a27b6906bf0ca707a2'
}
});
this.setState({ data: result.data.restaurants });
} catch (err) {
console.log(err);
} finally {
this.setState({ isLoading: false });
}
}
updateSearch = search => {
this.setState({ search });
};
searchReq = () => {
axios.request({
method: 'get',
url: `https://developers.zomato.com/api/v2.1/search?city_id=${city}&q${search}&category=${id}`,
header: {
'Content-Type': 'application/json',
'user-key': 'a31bd76da32396a27b6906bf0ca707a2'
}
});
this.setState({ data: result.data.restaurants });
}
render() {
const { search } = this.state;
return (
<SearchBar
placeholder="Type Here..."
onChangeText={this.updateSearch}
onSubmitEditing={this.searchReq}
value={search}
/>
)
}
}
如果有更高级的方法,我愿意学习新东西,我只想完成我想做的事情。此外,我知道如果我当前的方法有效,如果用户在两者之间添加 space 仍然会导致问题,所以我非常愿意学习新的和更高级的方法来做到这一点
我注意到你的搜索功能有几个错误。
- 您需要获取
city
、search
和id
值,这些值不在searchReq()
中
- 您需要先获取
result.data.restaurants
值,然后才能将其分配给data: result.data.restaurants
因为你已经分配了 this.setState({ search })
我在 searchReq()
中得到了那个值,如下所示,
searchReq = async () => {
try {
const result = await axios.request({
method: 'get',
url: `https://developers.zomato.com/api/v2.1/search?city_id=280&q${this.state.search}&category=11`,
headers: {
'Content-Type': 'application/json',
'user-key': 'a31bd76da32396a27b6906bf0ca707a2'
}
});
this.setState({ data: result.data.restaurants });
} catch (error) {
this.setState({ data: [] });
console.log(error);
}
}
所以完整的源码是这样的
import React, { Component } from 'react';
import {
View,
Text,
FlatList,
StyleSheet,
TouchableOpacity,
Dimensions,
ActivityIndicator,
} from 'react-native';
import { Card, Image, SearchBar, Icon } from 'react-native-elements';
import Logo from '../assets/Logo.png'
import axios from 'axios';
const SCREEN_WIDTH = Dimensions.get('window').width;
const SCREEN_HEIGHT = Dimensions.get('window').height;
export default class CategoryScreen extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
isVisible: true,
city: '280',
isLoading: true,
search: ''
}
}
async componentDidMount() {
try {
const result = await axios.request({
method: 'get',
url: `https://developers.zomato.com/api/v2.1/search?city_id=280&category=11`,
headers: {
'Content-Type': 'application/json',
'user-key': 'a31bd76da32396a27b6906bf0ca707a2'
}
});
this.setState({
data: result.data.restaurants,
isLoading: false
});
} catch (err) {
this.setState({ isLoading: false });
console.log(err);
}
}
updateSearch = search => {
this.setState({ search });
};
searchReq = async () => {
try {
const result = await axios.request({
method: 'get',
url: `https://developers.zomato.com/api/v2.1/search?city_id=280&q${this.state.search}&category=11`,
headers: {
'Content-Type': 'application/json',
'user-key': 'a31bd76da32396a27b6906bf0ca707a2'
}
});
this.setState({ data: result.data.restaurants });
} catch (error) {
this.setState({ data: [] });
console.log(error);
}
}
render() {
const { search } = this.state;
return (
<View>
<View style={styles.header}>
<Image source={Logo} style={{ resizeMode: 'stretch', width: 50, height: 50, alignSelf: 'center', justifyContent: 'center', marginTop: 30 }} />
<Icon
raised
name='location'
type='octicon'
color='#f50'
onPress={() => this.setState({ isModalVisible: !this.state.isModalVisible })}
containerStyle={{ alignSelf: 'flex-end', marginRight: 20, marginTop: -60 }} />
</View>
<SearchBar
placeholder="Type Here..."
onChangeText={this.updateSearch}
onSubmitEditing={this.searchReq}
value={search}
inputStyle={{ backgroundColor: 'steelblue', color: 'white' }}
inputContainerStyle={{ backgroundColor: 'steelblue', fontColor: 'white' }}
containerStyle={{ backgroundColor: 'steelblue', borderBottomColor: 'transparent', borderTopColor: 'transparent' }}
placeholderTextColor='white'
/>
{
this.state.isLoading ?
<View style={{ flex: 1, marginTop: 200 }}>
<ActivityIndicator style={{ color: 'red' }} />
</View> :
(
this.state.data.length == 0 ?
<View style={{ flex: 1, padding: 20, marginTop: 100 }}>
<Text style={{ color: '#000', fontWeight: 'bold' }}>No restaurants from selected category</Text>
</View> :
<View style={{ flexDirection: 'column' }}>
<FlatList
keyExtractor={item => item.id}
data={this.state.data}
renderItem={({ item }) =>
<TouchableOpacity onPress={() => console.log(item.restaurant.location.city)}>
<Card style={{ width: SCREEN_WIDTH }}>
<Image style={{ width: SCREEN_WIDTH / 3, height: 130 }} resizeMode="stretch" source={{ uri: item.restaurant.thumb }} />
<Text style={{ color: '#000', fontWeight: 'bold' }}>{item.restaurant.name} </Text>
</Card>
</TouchableOpacity>
}
/>
</View>
)
}
</View>
)
}
}
const styles = StyleSheet.create({
header: {
backgroundColor: '#ff4714',
height: SCREEN_HEIGHT / 8,
},
});
希望对您有所帮助。