尝试在反应中显示获取的数据时出现“TypeError:listOfTours.map 不是函数”

Posted

技术标签:

【中文标题】尝试在反应中显示获取的数据时出现“TypeError:listOfTours.map 不是函数”【英文标题】:"TypeError: listOfTours.map is not a function" while trying to display fetched data in react 【发布时间】:2022-01-09 00:22:18 【问题描述】:

这两天我一直在苦苦挣扎,经过数小时的反复试验,我无法解决它。

我想要实现的是我可以显示我从后端获取的获取的数据。我在不同的网站上看到了几个例子,但我无法让它工作。

这是我的代码和我得到的错误:

function Tours( isAuth: isAuth, component: Component, ...rest ) 
  const [listOfTours, setListOfTours] = useState([]);
  console.log(listOfTours);

  const getAllTours = () =>
    axios
      .get("/api/all-tours", 
        headers: 
          "x-access-token": localStorage.getItem("token"),
        ,
      )
      .then((response) => 
        if (response.data.status === "error") 
          console.log(response.data.status);
         else 
          setListOfTours(response.data);
        
      );

  useEffect(() => 
    getAllTours();
  , []);

  if (listOfTours.length > 0) 
    return (
      <div>
        <div className="tourDisplay">
          listOfTours.map((tour) => 
            return (
              <div>
                <div>Tourname: tour.tour_name</div>
                <div>...other values</div>
              </div>
            );
          )
        </div>
      </div>
    );
   else 
    return (
      <div>
        <p>Loading...</p>
      </div>
    );
  


export default withRouter(Tours);

TypeError: listOfTours.map is not a function
Tours
src/components/tours.js:32
  29 | if (listOfTours.length > 0) 
  30 |   return (
  31 |     <div>
> 32 |       <div className="tourDisplay">
     | ^  33 |         listOfTours.map((tour) => 
  34 |           return (
  35 |             <div>

我认为这与异步调用有关,并且 .map 无法处理空数组。因此,我在return前使用了if语句,但它也不起作用。

有人有什么想法吗,还是我错过了什么?

【问题讨论】:

似乎response.data 有一个名为status 的属性,这意味着它是一个对象而不是数组。当您调用setListOfTours(response.data) 时,您将尝试在该对象上调用map,这是无法完成的。你的response 是什么样的? 如果您在.then((response) =&gt; 中进行控制台登录,response.data 会是什么样子? 当你 console.log() 你确定response.data 是数组吗? @AndréKrosby 回复如下:pastebin.com/sQwu3m4X @hotcakedev response.data 看起来像:pastebin.com/Ft11q7iF 【参考方案1】:

尝试将getAllTours 函数作为Promise。

...
const [listOfTours, setListOfTours] = useState(null);

const getAllTours = async () => 
  try 
    // not sure if /api/all-tours is the proper API source
    const tours = await axios.get("/api/all-tours", 
        headers: 
          "x-access-token": localStorage.getItem("token"),
        ,
    );

    // try to console.log here to make sure if the tours has responded successfully and what type of the tours.response.data has either object or array
    console.log(tours.response);
    console.log(typeof tours.response.data);

    // this seems to be tours.response without data
    if (tours.response.data)  // if (tours.response) 
      // if tours.response.data is a type string, then convert it to json object
      // setListOfTours(JSON.parse(tours.response.data));
      setListOfTours(tours.response.data);
      // setListOfTours(tours.response);
    
   catch (err) 
    console.error(err);
  


  useEffect(() => 
    getAllTours();
  , [getAllTours]);

  return (
    <div>
      
        !listOfTours
          ? // loading div
          : <div className="tourDisplay">
          listOfTours.length > 0 && listOfTours.map((tour) => 
            return (
              <div>
                <div>Tourname: tour.tour_name</div>
                <div>...other values</div>
              </div>
            );
          )
        </div>
      
    </div>
  );

如果这不起作用,请检查浏览器并转到网络选项卡,然后确保 API 正常工作。

【讨论】:

tours.response.data = pastebin.com/Ft11q7iF, tours.response = pastebin.com/sQwu3m4X,在网络选项卡中显示状态代码 200。所以日期进来了,但不知何故 .map 不会使用数据 @Broump 刚刚更新了我的答案。看来您应该设置来自tours.response 的响应数据实际上没有数据。例如setListOfTours(tours.response); @Broump 请告诉我我的回答对你有用。 我的意思是从技术上讲它应该可以工作,但现在我又遇到了同样的错误。我还有其他方法可以达到同样的效果吗? @Broump,可能响应数据是字符串而不是 json 对象,所以请尝试 console.log(typeof tour.response.data)。如果它是一个数组,那么我的答案应该有效,否则您需要将 response.data 转换为 json 对象,例如 JSON.parse(response.data)【参考方案2】:

我不知道你的 response.data 是否是数组,但如果是数组,我可以写下一些解决方案,你可以尝试所有这些

检查数组是否为空

正如我在您的代码中看到的那样,您检查的是您的数组 truefalse ,这是错误的,因为 javscript 从不读取数组内部,您可以自己尝试 [] == [] 是错误的,所以每次当您获取数据,你保持你的状态为空,因为你的 if 语句总是返回 false 最好的检查方法是数组是否为空,你可以检查它的长度

错误

if (tours.response.data)  //it always returns false
    setListOfTours(tours.response.data);

如果您检查您的回复数据是否undefined 也会更好

更好

if (tours.response.data.length > 0 || !tours.response.data === undefined) 
    setListOfTours(tours.response.data);

在获取之前设置默认值

当您获取数据时,您的状态始终为 [] 空数组,如果您尝试在控制台中打印 listOfTours.tour_date,它将永远无法读取内部值,您将得到 无法读取 null 的属性(读取 'tour_date' ) 所以在获取数据之前创建带有类似字符串的空对象

const defaultState = 
  "tour_date": "",
  "tour_distance": 0,
  "tour_duration": 0,
  "tour_elevation_down": 0,
  "tour_elevation_up": 0,
  "tour_name": "",
  "tour_sport": ""


const [listOfTours, setListOfTours] = useState([defaultState]);

并且该代码将放松您的反应并且不会弹出错误,我在 null 属性的开头提到过

如果你声明有默认值,你可以制作简单的三元运算符来不 .map() 元素

!listOfTours[0].tour_date === "" ?
listOfTours.map(each => 
   return <div>...</div>
) : null

扩展运算符

解决该问题的最后一种方法我认为它不会起作用,但我也会包括那个,如果您的响应确实是数组并且反应无法识别它,您可以传播运算符

if (tours.response.data.length > 0 || !tours.response.data === undefined) 
      setListOfTours([...tours.response.data]);

此代码会将所有对象放入您的数组中并更新状态

如果其中一些有用,请告诉我

【讨论】:

以上是关于尝试在反应中显示获取的数据时出现“TypeError:listOfTours.map 不是函数”的主要内容,如果未能解决你的问题,请参考以下文章

将 no-cors 包含在标头中以获取 react.js 中的 json 内容时出现奇怪的错误

尝试在终端中启动反应应用程序时出现意外令牌 (9:13) 错误

在 angularjs 中的 onInit() 方法中获取用户详细信息后尝试显示用户详细信息时出现错误

尝试在 Flutter 中获取地点的自动完成位置并在点击的地点上显示详细信息时出现空安全错误

尝试输入反应应用程序路由时出现 404

尝试使用 jwt 从反应登录 api 时出现 401 状态