Реакция: отправка массива объектов из MongoDB (с использованием node.js + express) клиенту

Я пытаюсь отправить массив объектов, которые я получаю из MongoDB, клиенту (React.js) с помощью Node.js. Однако я продолжаю сталкиваться с ошибкой Objects are not valid as a React child (found: object with keys {_id, desc, price, purchased}), хотя уверен, что передал данные в правильном формате.

Как выглядит массив:

[{
          desc:"Manage",
          price: 5000,
          purchased: false,
        },
        {
          desc:"Deliver",
          price: 2000,
          purchased: false,
        },
        {
          desc:"Market",
          price: 4000,
          purchased: false,
        },
        {
          desc:"Agentone",
          price: 8000,
          purchased: false,
        },
        {
          desc:"CPM",
          price: 14000,
          purchased: false,
        },
        {
          desc:"Data",
          price: 17000,
          purchased: false,
        },
        {
          desc:"E-Sign",
          price: 9000,
          purchased: false,
        },
        {
          desc:"IGO",
          price: 3000,
          purchased: false,
        },
        {
          desc:"DocFast",
          price: 7000,
          purchased: false,
        }
      ],

Моя серверная сторона:

app.get('/item_info', (req, res) => {
  var data;
  MongoClient.connect(url, { useNewUrlParser: true }, function(err, db) {
    if (err) throw err;
    var dbo = db.db("ItemList");
    dbo.collection("ItemInfo").find().toArray(function(err, result) {
      if (err) throw err;
      res.send({express: result})
      db.close();
    });
  });
});

Мой клиент:

constructor(props){
  super(props)
  this.state = {
     itemList:[]
  }
}




componentDidMount() {
        this.callApi()
          .then(res => this.setState({itemList: res.express}))
          .catch(err => console.info(err));

      console.info(this.state.data)
  }

  callApi = async () => {
      const response = await fetch('/item_info');
      const body = await response.json();
      if (response.status !== 200) throw Error(body.message);

      return body;
  };

  render()  {
    return (
      <div>
        <div className = "App">
          <header className = "App-header">
            <img src = {logo} className = "App-logo" alt = "logo" />
            <h1 className = "App-title">Welcome to Reactr</h1>
          </header>
        </div>
        <div>{this.state.itemList[0]}</div>
     </div>
    )}

Чтобы убедиться, что клиент получает правильный формат, я распечатываю res.express на консоли, и он показывает следующее:

(9) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
0: {_id: "5bb223f5b717bc0aa0f5cf92", desc: "Manage", price: 5000, purchased: false}
1: {_id: "5bb223f5b717bc0aa0f5cf93", desc: "Deliver", price: 2000, purchased: false}
2: {_id: "5bb223f5b717bc0aa0f5cf94", desc: "Market", price: 4000, purchased: false}
3: {_id: "5bb223f5b717bc0aa0f5cf95", desc: "Agentone", price: 8000, purchased: false}
4: {_id: "5bb223f5b717bc0aa0f5cf96", desc: "CPM", price: 14000, purchased: false}
5: {_id: "5bb223f5b717bc0aa0f5cf97", desc: "Data", price: 17000, purchased: false}
6: {_id: "5bb223f5b717bc0aa0f5cf98", desc: "E-Sign", price: 9000, purchased: false}
7: {_id: "5bb223f5b717bc0aa0f5cf99", desc: "IGO", price: 3000, purchased: false}
8: {_id: "5bb223f5b717bc0aa0f5cf9a", desc: "DocFast", price: 7000, purchased: false}
length: 9
__proto__: Array(0)

Итак, клиент получает правильный формат массива. Я не могу понять, почему реакция кричит на меня

Можете показать, как реагируют на вас "крики"?

Matt Kuhns 01.10.2018 17:51

@MattKuhns Я получаю сообщение об ошибке: Objects are not valid as a React child (found: object with keys {_id, desc, price, purchased}

Spencer Ovetsky 01.10.2018 18:34

@MattKuhns также, когда я пытаюсь получить к нему доступ, выполнив {this.state.itemList[0].desc}, он говорит Cannot read property 0 of null, поэтому клиент не получает данные должным образом

Spencer Ovetsky 01.10.2018 18:35
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
3 163
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы пытаетесь визуализировать объект напрямую. Как вы можете видеть, просмотрев полученную ошибку, сделать это невозможно. Итак, вам нужно отобразить свойства этого объекта.

render() {
  return (
    <div>
      <div className = "App">
        <header className = "App-header">
          <img src = {logo} className = "App-logo" alt = "logo" />
          <h1 className = "App-title">Welcome to Reactr</h1>
        </header>
      </div>
      <p>{this.state.itemList[0].desc}</p>
      <p>{this.state.itemList[0].price}</p>
      // and so on
    </div>
  );
}

Конечно, вы не хотите визуализировать все объекты вручную. Итак, сначала используйте метод .map в своем массиве, а затем визуализируйте свойства.

class App extends React.Component {
  state = {
    itemList: [
      {
        _id: "1",
        desc: "Manage",
        price: 5000,
        purchased: false
      },
      {
        _id: "2",
        desc: "Deliver",
        price: 2000,
        purchased: false
      },
      {
        _id: "3",
        desc: "Market",
        price: 4000,
        purchased: false
      }
    ]
  };

  renderItems() {
    return this.state.itemList.map(item => (
      <div key = {item._id}>
        <p>Desc: {item.desc}</p>
        <p>Price: {item.price}</p>
        {!item.purchased ? <p>Not purchased</p> : <p>Purchased</p>}
      </div>
    ));
  }

  render() {
    return <div>{this.renderItems()}</div>;
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id = "root"></div>
this.state.itemList[0] возвращает ошибку Cannot read property '0' of null, поэтому настоящая проблема - это setstate, где itemList не получает данные должным образом.
Spencer Ovetsky 01.10.2018 18:34

И моя проблема в том, что если я делаю console.info (res.express), я действительно вижу данные, однако setstate просто не получает их

Spencer Ovetsky 01.10.2018 18:39

@SpencerOvetsky, это потому, что ваши данные поступают в результате асинхронной операции. В первом рендере нет itemList [0], поэтому вы не можете получить свойство из undefined. Вы пробовали мой код? Как отображение, а затем рендеринг элементов? Вы можете увидеть одно единственное свойство, подобное этому: { this.state.itemList[0] && this.state.itemList[0].desc } Но, опять же, большую часть времени вы хотите отобразить свои данные, а затем каким-то образом их визуализировать. Вы также можете снова выполнить условный рендеринг.

devserkan 01.10.2018 18:41

Я сделал. Это сработало. Есть ли работа, кроме использования карты? Поскольку мне нужно использовать эти данные в дочернем компоненте и отдельно изменять отдельный дочерний компонент (другой стиль). Работает ли использование axios?

Spencer Ovetsky 01.10.2018 18:49

В какой-то момент вам придется использовать .map. Наличие дочернего компонента не влияет на это, вместо прямого рендеринга просто передайте item дочернему компоненту и делайте там все, что захотите. axios или любой другой метод выборки не имеет отношения к вашей проблеме. Ваши данные поступают после первого рендеринга, поэтому вам следует выполнить условный рендеринг, если у вас есть проблемы с этим.

devserkan 01.10.2018 18:55

потому что мне нужно заключить все три моих дочерних компонента в строку и каждый дочерний компонент в столбец. и я, кажется, не могу понять это только с помощью карты. потому что внутри функции карты вы должны вернуть полный div, однако, если я хочу обернуть их в строку. Первый компонент будет иметь открывающий тег <div className = "row">, а третий дочерний компонент будет иметь </div>, поскольку они возвращают только часть тега div, это считается недопустимым синтаксисом.

Spencer Ovetsky 01.10.2018 19:04

Я не могу представить себе всю ситуацию прямо сейчас. Вы можете использовать React.Fragment вместо div везде, где вашему JSX нужна оболочка. Если проблема с этим вопросом решена для вас, примите мой ответ, задайте новый вопрос и опишите все подробности.

devserkan 01.10.2018 19:27

Добро пожаловать. Просто попробуйте написать код, и если вы столкнетесь с проблемой, не стесняйтесь задавать вопрос.

devserkan 01.10.2018 19:34

Другие вопросы по теме