0

I'm new to react native (Using Expo; I'm trying to learn it for a project I'll be doing with someone else) and I've been struggling with this for a couple of hours. I have searched for solutions to this error but I could not figure it out.

I have been following this tutorial to get some webscraping to work. The end goal is not an amazon list like the tutorial, but it should get the job done. I am using cheerio-without-node-native as the webscraping library.

I'm getting the error undefined is not a function (near '...this.state.items.map...') when trying to run the app. This is the file I'm working on:

  import { TouchableOpacity, ScrollView, StyleSheet } from 'react-native';
  import { ExpoLinksView } from '@expo/samples';
  import cio from 'cheerio-without-node-native';


  async function loadGraphicCards(page = 1) {
    const searchUrl = `https://www.amazon.de/s/?page=${page}&keywords=graphic+card`;
    const response = await fetch(searchUrl);  // fetch page 

    const htmlString = await response.text(); // get response text
    const $ = cio.load(htmlString);       // parse HTML string

    return $("#s-results-list-atf > li")             // select result <li>s
      .map((_, li) => ({                      // map to an list of objects
        asin: $(li).data("asin"),    
        title: $("h2", li).text(),    
        price: $("span.a-color-price", li).text(),
        rating: $("span.a-icon-alt", li).text(),
        imageUrl: $("img.s-access-image").attr("src")
      }));
}

  export default function LinksScreen() {

      state = { 
          page: 1,
          items: [], 
      };

      state.items = loadGraphicCards(state.page);

    return (
      // <ScrollView style={styles.container}>
      <ScrollView>
          {this.state.items.map(item => <Item {...item} key={item.asin}/>)}
      </ScrollView>
    );
  }

  LinksScreen.navigationOptions = {
    title: 'Readings',
  };

  const Item = props => (
      <TouchableOpacity onPress={() => alert("ASIN:" + props.asin)}>
          <Text>{props.title}</Text>
          <Image source={{uri: props.imageUrl}}/>
          <Text>{props.price}</Text>
          <Text>{props.rating}</Text>
      </TouchableOpacity>
  )

  const styles = StyleSheet.create({
    container: {
      flex: 1,
      paddingTop: 15,
      backgroundColor: '#ffffff',
    },
  });

I have already tried putting 'this' in various places, and while that may very well be the problem, those solutions were not working for me.

In your answer, can you please explain what was wrong, why, and if possible give resources to learn more?

Thanks!

Chad Wilson
  • 21
  • 1
  • 5

1 Answers1

0

actually you are trying to use state like class component in a functional component. So if I where you I'd do something like:

import React, { useState } from 'react';
//.....
export default function LinksScreen() {
    const [items, setItems] = useState([]);

    setItems(YOUR_ITEMS_FROM_SOMEWHERE));

    return (
      // <ScrollView style={styles.container}>
      <ScrollView>
          {items && items.map(item => <Item {...item} key={item.asin}/>)}
      </ScrollView>
    );
  }
Fábio BC Souza
  • 1,170
  • 19
  • 22
  • Thank you for the response! What should I put in place of `YOUR_ITEMS_FROM_SOMEWHERE` in my case? doing `setItems(loadGraphicCards(1))` gives me this error: `TypeError: undefined is not a function (near '...items.map...')` – Chad Wilson Jan 11 '20 at 16:42
  • Your loadGraphicCards function is kinf of weird, you are trying to load html in a reactNative app which is not allowed. You have to get json data and load it. You dont need jquery! – Fábio BC Souza Jan 11 '20 at 17:00