React js 给出错误对象作为 React 子对象无效,我使用了钩子

时间:2021-01-19 05:33:51

标签: reactjs react-hooks

我正在将数据从 Node JS 发送到数组对象中的 React JS。在 React JS 中,当我设置响应数据时,我收到错误“对象作为 React 子对象无效(找到:对象带有键 {eventName、eventDate、merchantid})。如果您打算呈现子集合,请使用数组相反。”

我查看了 Stackoverflow 的一篇帖子 useState Array of Objects。我也以同样的方式设置值,但出现错误。

下面是我从 Node JS 发送的数据。

[
  {
    eventName: 'Sankranti',
    eventDate: 2021-01-21T00:00:00.000Z,
    merchantid: 'tp012345'
  },
  {
    eventName: 'Sankranti 1',
    eventDate: 2021-01-26T00:00:00.000Z,
    merchantid: 'tp012345'
  }
]

在屏幕截图下方,我可以在控制台上看到错误和响应数据。 enter image description here

在我的代码下方,我在 setEventList(eventList => [...eventList, response]) 处遇到错误。根据我在代码下面添加的评论。

import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux';
import Carousel from 'react-bootstrap/Carousel'
import axios from 'axios';
import DashboardNavBar from './DashboardNavBar';
import Header from './Header';

const DashboardPage = (props) => {
    const [eventList, setEventList] = useState([])
    const [index, setIndex] = useState()

    if (!props.profileData) {
        useEffect(() => {
            (async () => {
                const eventsList = await axios.get(
                    "http://localhost:3000/api/dashboard"
                );
                    console.log(eventsList.data)
                    const response = eventsList.data
                    setEventList(eventList => [...eventList, response])
                    if(!response){
                        setErrorMsg('Please create Event and then add User !!')
                    }
            })();
        }, []);
    }

    const eventListRender = eventList.length > 0 ?
                        eventList.map((item,index) => {
                            console.log('item name: ', item[index].eventName)
                        return <Carousel.Item>{item[index].eventName}</Carousel.Item>
                        }) :
                        <Carousel.Item>No upcoming events</Carousel.Item>

    const handleSelect = (selectedIndex) => {
        console.log(eventList)
        console.log(selectedIndex)
        setIndex(selectedIndex)
    }

    return (
        <div>
            <DashboardNavBar />
            <Header />
            <p >Welcome !!!!!!</p>
            <Carousel
                activeIndex={index}
                onSelect={handleSelect}
                >
                {eventListRender}
            </Carousel>
        </div>
    );
}

const mapStateToProps = (state) => ({
    profileData: state.auth.profileData
})

export default connect(mapStateToProps) (DashboardPage);

添加下面的代码后,它总是读取第一次出现

const eventListRender = eventList.length > 0 ?
                        eventList.map((item,index) => {
                            console.log('item name: ', item[index].eventName)
                        return <Carousel.Item>{item[index].eventName}</Carousel.Item>
                        }) :
                        <Carousel.Item>No upcoming events</Carousel.Item>

请查找更新的结果

enter image description here

1 个答案:

答案 0 :(得分:1)

问题

好的,你的代码和盒子证实了我的怀疑。在您的沙箱中,您已将模拟响应作为平面数组直接放置在您的状态中

const [eventList, setEventList] = useState([
  {
    eventName: "Sankranti",
    eventDate: "2021-01-21T00:00:00.000Z",
    merchantid: "tp012345"
  },
  {
    eventName: "Sankranti 1",
    eventDate: "2021-01-26T00:00:00.000Z",
    merchantid: "tp012345"
  }
]);

这允许渲染按预期工作,只需映射这个平面对象数组。

eventList.map((item, index) => {
  return <Carousel.Item>{item.eventName}</Carousel.Item>;
})

但是在您的原始代码中,您没有将状态更新为平面数组。 response 一个数组,即 [object1, object2] 并且您将此数组附加到您所在州的 eventList 数组的末尾。

setEventList(eventList => [...eventList, response])

这会将您的状态更新为类似 [[object1, object2]] 的内容,因此您使用的映射函数仅映射一个元素。

eventList.map((item, index) => {
  return <Carousel.Item>{item[index].eventName}</Carousel.Item>;
})

原因是因为您使用了外层的数组索引(回忆一下eventList是一个长度为1的数组)来访问内层嵌套数组(长度为 2 的数组)。在迭代外部数组时,index 仅达到值 0,因此仅呈现内部数组的第零个元素。

在此代码中查看更准确的问题重现:

const response = [
  {
    eventName: "Sankranti",
    eventDate: "2021-01-21T00:00:00.000Z",
    merchantid: "tp012345"
  },
  {
    eventName: "Sankranti 1",
    eventDate: "2021-01-26T00:00:00.000Z",
    merchantid: "tp012345"
  }
];

function App() {
  const [eventList, setEventList] = useState([]);

  useEffect(() => {
    setEventList((eventList) => [...eventList, response]);
  }, []);

  const eventListRender =
    eventList.length > 0 ? (
      eventList.map((item, index) => {
        return <Carousel.Item>{item[index].eventName}</Carousel.Item>;
      })
    ) : (
      <Carousel.Item>No upcoming events</Carousel.Item>
    );
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>

      <Carousel>{eventListRender}</Carousel>
    </div>
  );
}

解决方案

如果响应数据也是一个数组,那么您似乎应该将它扩展到您的 eventList 状态数组中,这样它仍然是一个不错的平面数组。

此外,正如@Ashish 所指出的,您的 useEffect 钩子用法是无效的,并且通过放置在条件块中而违反了钩子的规则。效果需要在组件的主体中,因此应该在效果回调中测试条件。将匿名 async 函数重构为标准命名函数,并在条件检查调用效果回调。

useEffect(() => {
  const getEvents = async () => {
    const eventsList = await axios.get("http://localhost:3000/api/dashboard");
    console.log(eventsList.data);
    const response = eventsList.data;
    setEventList((eventList) => [
      ...eventList, // <-- copy previous state
      ...response, // <-- spread array response
    ]);
    if (!response) {
      setErrorMsg("Please create Event and then add User !!");
    }
  };

  if (!props.profileData) { // <-- check condition for fetching data
    getEvents();
  }
}, []);

const eventListRender =
  eventList.length > 0 ? (
    eventList.map((item, index) => {
      return <Carousel.Item key={index}>{item.eventName}</Carousel.Item>;
    })
  ) : (
    <Carousel.Item>No upcoming events</Carousel.Item>
  );

使用模拟 axios 数据获取的演示。

Edit react-js-giving-error-objects-are-not-valid-as-a-react-child-i-used-hooks