【问题标题】:React js giving error Objects are not valid as a React child, I used hooksReact js给出错误对象作为React子无效,我使用了钩子
【发布时间】:2021-01-19 05:33:51
【问题描述】:

我正在将数据从 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'
  }
]

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

在我的代码下方,我在 setEventList(eventList => [...eventList, response]) 处遇到错误。基于 cmets 我在下面添加了代码。

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>

请查找更新后的结果

【问题讨论】:

  • 这个错误发生在你试图渲染你的状态的地方,你能包括一个完整的组件代码示例吗?
  • 一个看起来不对的地方是response 是一个数组,所以它应该是setEventList(eventList =&gt; [...eventList, ...response])
  • 嗨 Drew Reese,我添加了如下代码,现在错误消失了,但现在没有读取对象(item.eventName = undefined)。常量 eventListRender = eventList.length > 0 ? eventList.map((item) => { console.log('item name: ', item.eventName) return {item.eventName} }) : No即将发生的事件
  • 您能否更新您的问题,即新代码,所以 cmets 不适用于代码块显示。那里的代码很难阅读。
  • 这可能与错误消息没有直接关系,但您正在从不允许的条件中调用 useEffect 挂钩。 Hook Rules.

标签: reactjs react-hooks


【解决方案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>;
})

原因是因为你使用了 outer 的数组索引(回想一下eventList 是一个长度为 1 的数组)来访问 inner 嵌套数组(数组长度为 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 数据获取的演示。

【讨论】:

  • 感谢 Drew Reese,它成功了。非常感谢您的清晰解释。
  • @bobapoorna 欢迎您!如果您发现答案和解释有帮助,那么也请不要忘记投票。干杯。
猜你喜欢
  • 2021-08-05
  • 2018-11-12
  • 1970-01-01
  • 2020-05-12
  • 1970-01-01
  • 2021-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多