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

React Native电影搜索App报错:Cannot read property 'map' of undefined

问题分析与解决

核心问题

  1. 初始状态类型不匹配:你把movies的初始状态设为数组[],但fetchMovies返回的是包含Search数组的对象(比如{ Search: [...] })。组件首次渲染时,movies是数组,movies.Search自然为undefined,直接调用map就会触发报错。
  2. 未处理数据加载前的空值:即便修正初始状态,API请求完成前movies.Search仍可能是undefined,直接调用map会引发错误。

修复步骤

1. 修正初始状态类型

将movies的初始状态改为空对象,匹配API返回的数据结构:

const [movies, setMovies] = useState({});

2. 安全调用map方法

在调用map前,先判断movies.Search是否存在,或使用可选链操作符(?.)避免空值报错:

{
  movies.Search?.map((movie,i)=>(
    <MovieCard movie={movie} key={i}/>
  ))
}

也可以用更严谨的判断逻辑:

{
  movies.Search && Array.isArray(movies.Search) && movies.Search.map((movie,i)=>(
    <MovieCard movie={movie} key={i}/>
  ))
}

3. 调整Header显示逻辑(可选)

原代码中Object.keys(movies).length > 0的判断会导致初始状态下Header不显示,若想一开始就展示搜索栏,可直接去掉该判断:

<View style={styles.Header}>
  <TextInput style={styles.SearchBar} placeholder='Search...' 
    value={searchMovie} onChangeText={(text)=>setSearchMovie(text)}
    left = {<TextInput.Icon name='magnify'/>} onPress={Search}
    onSubmitEditing={Search}/>
  <Button
  title="Search"
  onPress={() => navigation.navigate('Info')}
  />
</View>

完整修改后的代码

import React, { useEffect, useState } from 'react';
import {StyleSheet,View,Button,ScrollView} from 'react-native';
import {TextInput} from 'react-native-paper'; 

import { fetchMovies } from '../API/Index';
import {MovieCard} from './MovieCard';

function SearchScreen({navigation}) {
  // 修正初始状态为对象
  const [movies, setMovies] = useState({});
  console.log(movies);
  const [searchMovie, setSearchMovie] = useState('Harry Potter');

  useEffect(()=>{
    const getMovies = async() =>setMovies(await fetchMovies(searchMovie))
    getMovies();
  },[])

  const Search = async () => {
    setMovies(await fetchMovies(searchMovie));
    setSearchMovie('');
  };
  
  return (
    <View style={styles.Container}>
      {/* 去掉判断,始终显示Header */}
      <View style={styles.Header}>
        <TextInput style={styles.SearchBar} placeholder='Search...' 
          value={searchMovie} onChangeText={(text)=>setSearchMovie(text)}
          left = {<TextInput.Icon name='magnify'/>} onPress={Search}
          onSubmitEditing={Search}/>
        <Button
        title="Search"
        onPress={() => navigation.navigate('Info')}
        />
      </View>
      <ScrollView contentContainerStyle={{
        flexDirection: 'row',
        flexWrap: 'wrap',
        justifyContent: 'space-around',
        alignItems: 'center'
      }}>
        {/* 使用可选链安全调用map */}
        {
          movies.Search?.map((movie,i)=>(
            <MovieCard movie={movie} key={i}/>
          ))
        }
      </ScrollView>
  </View>
  );
}

const styles = StyleSheet.create({
  Container:{
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center'
  },
  Header:{
    flexDirection: 'row',
    backgroundColor:'#000000',
    alignItems: "center",
    justifyContent: 'center',
    width:'100%'
  },
  SearchBar:{
    borderColor: "#FFFFFF",
    backgroundColor: "#DDDDDD",
    marginHorizontal: 5
  },
});

export default SearchScreen;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 10:15:33