"TypeError: listOfTours.map is not a function" while trying to display fetched data in react

"TypeError: listOfTours.map is not a function" while trying to display fetched data in react

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

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

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

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语句,但也不行。

有人知道吗,还是我遗漏了什么?

尝试使 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 正常工作。

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

检查数组是否为空

正如我在你的代码中看到的那样,你检查的是你的数组 truefalse ,这是错误的,因为 javscript 从不读取内部数组,你可以自己尝试 [] == [] 是 false 所以每次当你获取数据时你保持你的状态为空因为你的 if 语句总是 returns 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]);
}

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

如果其中一些可行,请告诉我