简体   繁体   中英

TypeError: undefined is not a function (near '…data.map…')

I updated my code thanks to your help. When I launch the app with Expo, the opening works but I lost my scan icon which does not appear in my screen. This icon appeared previously. The idea is to scan some barcodes in order to display relevant data stemming from products.

Here is my new code:

import React, { useState, useEffect } from "react";
import {
  StyleSheet,
  Text,
  View,
  FlatList,
  Button,
  AsyncStorage,
} from "react-native";
import { useNavigation } from "@react-navigation/core";
import { TouchableOpacity } from "react-native-gesture-handler";
import { FontAwesome5 } from "@expo/vector-icons";
import { MaterialCommunityIcons } from "@expo/vector-icons";
import { ActivityIndicator } from "react-native-paper";

function ProductsScreen() {
  const navigation = useNavigation();
  const [data, setData] = useState([]);
  const [isLoading, setisLoading] = useState(true);

  useEffect(() => {
    const fetchData = async () => {
      const data = await AsyncStorage.getItem("userData");

      setData(data);
      setisLoading(false);
    };
    fetchData();
  }, []);

  console.log(data);
  return isLoading ? (
    <ActivityIndicator />
  ) : (
    <>
      {data ? (
        <FlatList
          data={dataArray}
          keyExtractor={(item) => item.name}
          renderItem={({ item }) => (
            <>
              <Text>{item.brand}</Text>

              <View style={styles.scan}>
                <MaterialCommunityIcons
                  name="barcode-scan"
                  size={40}
                  color="black"
                  onPress={() => {
                    navigation.navigate("CameraScreen");
                  }}
                />
              </View>
            </>
          )}
        />
      ) : null}
    </>
  );
}
export default ProductsScreen;

I would appreciate your comments please.

You could use? (optional chaining) to confirm data doesnt yield to undefined before mapping.

data?.map((data, index) => {return <>....</>}

You need to return from data.map function to render the array items

 return isLoading? ( <ActivityIndicator /> ): ( <> {data?.map((data, index) => { return <View key ={index}> <Text> {data.products_name_fr} </Text> <Text> {data.brands} </Text> <Text> {data.image_url} </Text> <View style={styles.scan}> <MaterialCommunityIcons name="barcode-scan" size={40} color="black" onPress={() => { navigation.navigate("CameraScreen"); }} /> </View> </View>; })} </> );

Or short-hand of return

 return isLoading? ( <ActivityIndicator /> ): ( <> data?.map((data, index) => ( <View key ={index}> <Text> {data.products_name_fr} </Text> <Text> {data.brands} </Text> <Text> {data.image_url} </Text> <View style={styles.scan}> <MaterialCommunityIcons name="barcode-scan" size={40} color="black" onPress={() => { navigation.navigate("CameraScreen"); }} /> </View> </View>; )) </> );

I changed my code like this but I have the same error. Besides, the part of code which begins from: const styles=Stylesheet.create seems to be not active

import React, { useState, useEffect } from "react";
import { StyleSheet, Text, View, Button, AsyncStorage } from "react-native";
import { useNavigation } from "@react-navigation/core";
import { TouchableOpacity } from "react-native-gesture-handler";
import { FontAwesome5 } from "@expo/vector-icons";
import { MaterialCommunityIcons } from "@expo/vector-icons";
import { ActivityIndicator } from "react-native-paper";
import axios from "axios";

function ProductsScreen() {
  const navigation = useNavigation();
  const [data, setData] = useState([]);
  const [isLoading, setisLoading] = useState(true);

  useEffect(() => {
    const fetchData = async () => {
      const data = await AsyncStorage.getItem("userData");

      setisLoading(false);
      setData(data);
    };
    fetchData();
  }, []);

  return isLoading ? (
    <ActivityIndicator />
  ) : (
    <>
      {data?.map((data, index) => {
        return (
          <>
            key ={index}
            <Text> {data.products_name_fr} </Text>
            <Text> {data.brands} </Text>
            <Text> {data.image_url} </Text>
            <View style={styles.scan}>
              <MaterialCommunityIcons
                name="barcode-scan"
                size={40}
                color="black"
                onPress={() => {
                  navigation.navigate("CameraScreen");
                }}
              />
            </View>
          </>
        );
      })}
    </>
  );

  const styles = StyleSheet.create({
    products: {
      alignItems: "center",
      justifyContent: "center",
    },

    scan: {
      marginLeft: 30,
      position: "absolute",
      bottom: 0,
      right: 20,
      marginBottom: 60,
      marginRight: 30,
      padding: 10,
      borderRadius: 10,
      backgroundColor: "#ff9234",
    },
  });
}
export default ProductsScreen;

I changed a little bit my code and I got another type of error: Invariant violation: Text strings must be rendered within a component. I will really appreciate your comments and support to fix this

return isLoading ? (
    <ActivityIndicator />
  ) : (
    <>
      data?.map((data, index) => (
      <>
        <Text> {data.products_name_fr} </Text>
        <Text> {data.brands} </Text>
        <Text> {data.image_url} </Text>
        <View style={styles.scan}>
          <MaterialCommunityIcons
            name="barcode-scan"
            size={40}
            color="black"
            onPress={() => {
              navigation.navigate("CameraScreen");
            }}
          />
        </View>
      </>
      ))
    </>
  );
}

In the useEffect, set the data as array. Example

const = [data, setData] = useState([]); // do this in your state

setData([data]); //do this in your useEffet hook

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM