0

I am new to using APIs with React Native, I have a few things figured out but what I'm trying to do now is create a Search function. I've tried a few things so far, but either the function isn't being called, or I get an error about the function being called as an object. Also, I am using axios to make this API call

Here's what I've got so far.

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}
            />
        )
    }
}

If there is a more advanced way of doing it I'm open to learning something new, I just want to accomplish what I want to do. Also, I know that if my current method worked it'd still cause problems if the user adds a space in between, so I'm very open to learning new and more advanced ways of doing this

Here is the expo snack https://snack.expo.io/SJoIr8u1I

SDushan
  • 4,341
  • 2
  • 16
  • 34
CoolMAn
  • 1,851
  • 2
  • 12
  • 23
  • can you share the code in an expo snack? ill check there – Gaurav Roy Dec 30 '19 at 05:07
  • @CoolMAn I can't run your expo snack, so many errors. After fixing them and pointing your LOGO to the only image asset I was able to run it. Line ~27: `this.props.navigation` is undefined, so when trying to access `navigate` it fails. You don't call `this.navigate` though. https://snack.expo.io/ryiOgvuJI – Drew Reese Dec 31 '19 at 05:45
  • @DrewReese I apologize for that. I use navigation to go to another screen, however I must've removed the rest of the code regarding it and forgot about this one. – CoolMAn Dec 31 '19 at 06:08
  • @CoolMAn Ah, in that case, it all seemed to work with that commented out. (after fixing the other errors) – Drew Reese Dec 31 '19 at 06:13
  • @DrewReese the search function works and shows results related to the search? it still isn't working for me :\ – CoolMAn Dec 31 '19 at 06:18

1 Answers1

1

I noted couple of mistake of your search function.

  1. You need to get city, search & id value which are not in searchReq()
  2. You need to get result.data.restaurants value before you assign it to data: result.data.restaurants

Since you already assign this.setState({ search }) I get that value inside searchReq() as below,

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);
    }
}

So full source code will be like this

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,

    },
});

Hope this helps you.

SDushan
  • 4,341
  • 2
  • 16
  • 34
  • so, I try this and there are no errors! however the results aren't displayed – CoolMAn Dec 31 '19 at 06:31
  • @CoolMAn make sure that you are passing correct params to search query. – SDushan Dec 31 '19 at 06:37
  • I've added a `console.log('check')` in the function and nothing shows up in the terminal when I press enter key on the keyboard, perhaps the function is not being called – CoolMAn Dec 31 '19 at 06:51
  • @CoolMAn where did you add ```console.log('check')```? – SDushan Dec 31 '19 at 07:10
  • in the `try {}` section of the `searchReq` function – CoolMAn Dec 31 '19 at 07:11
  • ```try{}``` will not called because there is an issue while requesting ```https://developers.zomato.com/api/v2.1/search?city_id=280&q${this.state.search}&category=11```. So it immediately called ```catch{}``` – SDushan Dec 31 '19 at 07:19
  • well the terminal doesn't log any error nor does it log `check` if I add `console.log('check')` in the `catch{}` section.... – CoolMAn Dec 31 '19 at 07:28
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/205130/discussion-between-sdushan-and-coolman). – SDushan Dec 31 '19 at 07:59