Firebase: snapshot.val не является функцией или возвращаемое значение не повторяется

Итак, я создаю небольшое приложение, используя Express, Firebase и ReactJS. Я наткнулся на проблему с Firebase snapshot.val

Эта часть кода на экспрессе обслуживает мои поездки по идентификатору и получает все. Для всех поездок работает нормально, но когда я пытаюсь перейти к одиночной поездке, мне возвращается эта ошибка.

если я деструктурирую его как массив:

UnhandledPromiseRejectionWarning: TypeError: snapshot.val is not a function or its return value is not iterable

Если я деструктурирую его как объект:

TypeError: Cannot destructure property trip of 'undefined' or 'null'.

и я полностью сбит с толку и не могу найти решение.

Вот экспресс-часть кода:

const firebase = require('firebase');

const reference = () => firebase.database().ref('/trips')

exports.getSingle = async (id) => {
  //const snapshot = await reference()
  //  .orderByChild('id')
  //  .equalTo(id)
  //  .limitToFirst(1)
  //  .once('value');

  // const [trip] = snapshot.val();
  //  return trip
const snapshot = await reference()
    .orderByChild('id')
    .equalTo(parseInt(id, 10))
    .limitToFirst(1)
    .once('value');
  let trip = [];
  snapshot.forEach(function (tripSnapshot) {
    tripStorage = tripSnapshot.val();
    console.info(tripStorage);
    trip.push(tripStorage);
  });
  console.info(trip);
  return trip;
};

exports.getAll = async () => {
  const snapshot = await reference().once('value');

  return snapshot.val();
};

Я получаю поездки в интерфейсе с помощью:

 componentDidMount() {
    fetch("/api/trips/get/" + this.state.id)
      .then(res => res.json())
      .then(trip =>
        this.setState({
          trip
        }, () => console.info("Trips fetched...", trip))
      );
  }

Контроллер для поездок:

const express = require('express');

const route = express.Router();
const tripUtil = require('../utils/tripUtil');

route.get('/getAll', async (req, res) => {
  const trips = await tripUtil.getAll();

  res.json(trips);
});

route.get('/get/:id', async (req, res) => {
  const { id } = req.params;
  const trip = await tripUtil.getSingle(id);

  if (trip) {
    res.json(trip);
  } else {
    res.status = 400;
    res.json({
      error: 'trip not found'
    });
  }
});

module.exports = route;

И сопоставление свойств объекта следующим образом:

 {this.state.trip.itinerary.days.map((day, i) => {
     return (
       <div key = {i} className = "trip-single-item__day">
          <div className = "trip-single-item__day-header">
              <div className = "trip-single-item__day-title">
                 {day.title}
              </div>
              <div className = "trip-single-item__day-subtitle">
                 {day.subtitle}
              </div>
              <div className = "trip-single-item__day-date">
                 {day.date}
              </div>
          </div>
          <div className = "trip-single-item__day-body">
             <div className = "trip-single-item__day-descritpion">
               {day.description}
             </div>
          </div>
      </div>
      );
  })}

Вот изображение одной поездки Одиночная поездка в firebase

Любые предложения или направления? Спасибо

почему вы заключаете константу trip в квадратные скобки? const [trip] = snapshot.val(); Вы пытаетесь получить доступ к свойству trip из snapshot.val(), например const { trip } = snapshot.val();

Hristo Eftimov 20.03.2019 10:42

Если я размещу его так, как вы предлагаете, я получу UnhandledPromiseRejectionWarning: TypeError: Cannot destructure property trip «undefined» или «null». Но я подумал, что это правильный способ деконструировать объект firebase?

squizyt 20.03.2019 11:28

это был просто вопрос, а не предложение :) Можешь отредактировать свой пост и написать ошибку: it returns me this error and I am totally baffled

Hristo Eftimov 20.03.2019 11:36

Готово, спасибо за подсказку. Почему я это делаю? Когда я немного думаю об этом, если он хранится как объект в firebase, тогда нет логики для доступа к нему через квадратные скобки, но теперь я еще больше запутался, почему поездка не определена.

squizyt 20.03.2019 11:48

Является ли свойство id вложенным свойством одного объекта trip? Если нет, вы можете получить к нему доступ следующим образом: reference().child(id).once('value')`

Hristo Eftimov 20.03.2019 12:03

Да, идентификатор является вложенным объектом одиночного trip.

squizyt 20.03.2019 12:19

Я пытался воспроизвести вашу проблему, но безуспешно. У меня есть несколько вопросов: вы звоните firebase.initializeApp перед вашей просьбой? И другая идея - проверить правила вашей базы огня. Есть ли у вас какие-либо особые правила или проверки в отношении одного объекта поездки?

Hristo Eftimov 20.03.2019 13:43

Да, я звоню firebase.initializeApp. Правила тоже в порядке. Если вы посмотрите, есть код для получения всех поездок, я предполагаю, что он не будет работать, если firebase.initializeApp и правила не сохранены должным образом. Я также прикреплю структуру базы данных в редактировании.

squizyt 20.03.2019 13:57

К сожалению, у меня больше нет идей. Вы уверены, что getSingle получает правильный id в качестве параметра? Вы можете попробовать упростить запрос... начните с await reference().once('value'), затем попробуйте с await reference().child(0).once('value') и проверьте результаты. Также уберите эти квадратные скобки, просто const trip = snapshot.val(); return trip;

Hristo Eftimov 20.03.2019 14:03

Поместите свой код, чтобы сначала попытаться поймать. Посмотрите на ошибку. Я думаю, вы пропустили добавление правил в firebase, поэтому нет ошибки разрешения.

tuledev 21.03.2019 04:34
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
10
3 039
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Может быть UnhandledPromiseRejectionWarning.

Обработайте свой снимок с помощью then/catch

exports.getSingle = async (id) => {
  await reference()
    .orderByChild('id')
    .equalTo(id)
    .limitToFirst(1)
    .once('value').then(snapshot => {

         const [trip] = snapshot.val();
         return trip

        //  console.info(post.id)  if required
    })
};

Да выдает, UnhandledPromiseRejectionWarning Я отредактировал ошибку. Просматривал документацию firebase и пробовал некоторые варианты, как вы опубликовали, но все равно выдает ту же ошибку.

squizyt 20.03.2019 12:16
Ответ принят как подходящий

Firebase обычно не рекомендует хранить данные в виде массивов в базе данных реального времени (хотя существуют некоторые исключения): https://firebase.googleblog.com/2014/04/best-practices-arrays-in-firebase.html

Я предполагаю, что по какой-то причине значение вашего снимка отображается не как массив, а как объект с числовыми ключами. Одной из причин этого может быть то, что ключи в Firebase не являются строго последовательными, поскольку Firebase будет отображать ваши данные в виде массива только в том случае, если ключи данных начинаются с 0 и нет пробелов.

Можете ли вы попробовать этот код, чтобы увидеть, работает ли он?

exports.getSingle = async (id) => {
  const snapshot = await reference()
    .orderByChild('id')
    .equalTo(id)
    .limitToFirst(1)
    .once('value');

  const queryResult = snapshot.val()
  console.info(queryResult) // Make note of the object shape here. Make sure there are actually results.

  const trip = Object.values(queryResult)[0]
  return trip;
};

Он просто возвращает queryResult как null, поэтому кажется, что ссылка на базу данных не годится. Я также отредактировал код контроллера, который обслуживает идентификатор и все, может быть, я что-то упускаю?

squizyt 21.03.2019 18:43

Похоже, что .orderByChild, .equalTo и limitToFirst создают проблему, и я не могу понять, почему.

squizyt 22.03.2019 00:07

Параметр :id, который вы получаете от Express и передаете в getSingle, скорее всего, является строкой, а свойство id поездки в Firebase — числом. Это может привести к сбою вашего запроса equalTo, поскольку он не может найти элемент с идентификатором === "1". Попробуйте equalTo(parseInt(id, 10)) и посмотрите, решит ли это проблему.

Ragnar Mikael Halldórsson 22.03.2019 13:13

Да, это решило часть с идентификатором, который, очевидно, был строкой. Но довольно странная вещь происходит после того, как мне пришлось обновить код для помещения snapshot.val() в массив отключения, и отправленные элементы отображаются в JSON нормально до того, как они будут отправлены, но при перемещении вложенные элементы внутри отображаются как [object Object].

squizyt 22.03.2019 14:44

Глубоко вложенные объекты JSON часто отображаются как [Object] или [object Object] при входе в консоль с помощью console.info. Это нормально. Вы можете попробовать console.info(JSON.stringify(trips, null, 2)) сериализовать объект и распечатать его в виде строки.

Ragnar Mikael Halldórsson 25.03.2019 15:32

Это беспокоило меня, и я все-таки это понял, но мне удалось сделать это, 2 вещи отсутствовали equalTo(parseInt(id, 10)) и этот фрагмент кода для рендеринга поездок pastebin.com/V6EgP3SB

squizyt 26.03.2019 12:47

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