You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native使用Map传递Props报错:undefined is not a function

问题:Sanity数据获取后无法通过Props传递给子组件ResturantCard

尝试从Sanity CMS获取数据并通过Props传递给子组件ResturantCard,但功能失效。相同代码在其他页面可正常运行,当前页面在resturants?.map(...)处报错。已通过console.log确认数据已获取,但无法传递。


报错代码片段

{resturants?.map((type) => {
      return (
        <ResturantCard
          key={type._id}
          id={type._id}
          imgUrl="https://links.papareact.com/gn7"
          title={type.name}
          genre={type.genre}
          address={type._address}
          description={type.description}
          lat={type.lat}
          long={type.long}
          dishes={type.dishes}
        />
      );
    })}

父组件FeaturedRow完整代码

import { View, Text, ScrollView } from "react-native";
import { React, useEffect, useState } from "react";
import { ArrowRightIcon } from "react-native-heroicons/outline";
import ResturantCard from "./ResturantCard";
import client from "../sanity";

export default function FeaturedRow(props) {
  const [resturants, setResturants] = useState([]);
  useEffect(() => {
    console.log(props.id);
    client
      .fetch(
        `*[_type == "featured" && _id== $id ]{...,type[]->{ 
          ...,dishes[]->, type->{name}       
          },
        }[0]`,
        { id: props.id }
      )
      .then((data) => setResturants(data), console.log("date recieved"))
      .catch(console.log("No data received"));
  }, []);

  console.log(resturants);

  return (
    <View>
      <View className="flex-row mt-4 items-center justify-between px-4">
        <Text className="font-bold text-lg">{props.title}</Text>
        <ArrowRightIcon />
      </View>
      <Text className="text-xs px-4 text-gray-500">{props.description}</Text>
      <ScrollView
        horizontal
        contentContainerStyle={{
          paddingHorizontal: 15,
          paddingBottom: 15,
        }}
        className="pt-4 pb-2"
      >
        {resturants?.map((type) => {
          return (
            <ResturantCard
              key={type._id}
              id={type._id}
              imgUrl="https://links.papareact.com/gn7"
              title={type.name}
              genre={type.genre}
              address={type._address}
              description={type.description}
              lat={type.lat}
              long={type.long}
              dishes={type.dishes}
            />
          );
        })}
        <ResturantCard
          id="d1"
          imgUrl="https://links.papareact.com/gn7"
          title="Ramzan Shinwari"
          genre="Dessi Food"
          address="123 Chaklala"
          description="The Best Food in the Town"
          lat="121343"
          long="453233"
          dishes={[]}
        />
        <ResturantCard
          id="d1"
          imgUrl="https://links.papareact.com/gn7"
          title="Ramzan Shinwari"
          genre="Dessi Food"
          address="123 Chaklala"
          description="The Best Food in the Town"
          lat="121343"
          long="453233"
          dishes={[]}
        />
        <ResturantCard
          id="d1"
          imgUrl="https://links.papareact.com/gn7"
          title="Ramzan Shinwari"
          genre="Dessi Food"
          address="123 Chaklala"
          description="The Best Food in the Town"
          lat="121343"
          long="453233"
          dishes={[]}
        />
      </ScrollView>
    </View>
  );
}

子组件ResturantCard完整代码

import { View, Text, TouchableOpacity, Image } from "react-native";
import React from "react";
import { MapPinIcon, StarIcon } from "react-native-heroicons/outline";

export default function ResturantCard(props) {
  return (
    <TouchableOpacity className="bg-white shadow mr-4">
      <Image source={{ uri: props.imgUrl }} className="h-36 w-64" />
      <View className="px-3 pb-3">
        <Text className="text-lg font-bold pt-2">{props.title}</Text>
        <View className="flex-row items-center space-x-1">
          <StarIcon color="green" size={22} opacity={0.5} />
          <Text>
            {props.rating} . {props.genre}
          </Text>
        </View>
        <View className="flex-row items-center space-x-1">
          <MapPinIcon />
          <Text className="text-xs text-gray-500">Near . {props.address}</Text>
        </View>
      </View>
    </TouchableOpacity>
  );
}

控制台输出

控制台显示已成功获取到包含_id、name、type等字段的对象,但调用map方法时触发错误。


解决方案

问题核心是数据结构不匹配:

  1. Sanity查询返回的data是单个对象(查询末尾的[0]导致),但你将其赋值给了数组类型的状态resturants,而对象没有map方法,因此报错。
  2. 实际的餐厅列表在返回对象的type属性中,而非整个data本身。

修改步骤:

  1. 修正then回调中的状态赋值逻辑,提取data中的type数组:
.then((data) => {
  setResturants(data?.type || []); // 若data.type为空,默认赋值空数组避免报错
})
  1. 补充useEffect的依赖数组,加入props.id,确保props.id变化时重新查询数据:
useEffect(() => {
  // 原有查询代码
}, [props.id]);
  1. 可选修复:子组件中使用的props.rating未在父组件传递,会显示undefined,建议在父组件补充传递该字段,或在子组件中做兜底处理(如{props.rating || '0'})。

内容的提问来源于stack exchange,提问作者Ammar Hassan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 09:49:17