使用 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 仍然会导致问题,所以我非常愿意学习新的和更高级的方法来做到这一点

这里是世博小吃https://snack.expo.io/SJoIr8u1I

我注意到你的搜索功能有几个错误。

  1. 您需要获取 citysearchid 值,这些值不在 searchReq()
  2. 您需要先获取 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,

    },
});

希望对您有所帮助。