#javascript #node.js #reactjs #firebase #express
#javascript #node.js #reactjs #firebase #выразить
Вопрос:
Итак, я создаю небольшое приложение, используя Express, Firebase и ReactJS. Я застопорился из-за проблемы с Firebase snapshot.val
Эта часть кода в express обслуживает мои поездки по идентификатору и для получения всех. Для всех поездок работает нормально, но когда я пытаюсь перейти к единственной поездке, она возвращает мне эту ошибку
если я разрушу его как массив:
Предупреждение о необработанном promiserejectionwarning: TypeError: snapshot.val не является функцией или его возвращаемое значение не является итеративным
Если я разрушу его как объект:
Ошибка типа: не удается уничтожить свойство
trip
, имеющее значение ‘undefined’ или ‘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.log(tripStorage);
trip.push(tripStorage);
});
console.log(trip);
return trip;
};
exports.getAll = async () => {
const snapshot = await reference().once('value');
return snapshot.val();
};
Я извлекаю trips во внешнем интерфейсе с:
componentDidMount() {
fetch("/api/trips/get/" this.state.id)
.then(res => res.json())
.then(trip =>
this.setState({
trip
}, () => console.log("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>
);
})}
Вот изображение одного отключения Single trip в firebase
Есть предложения или указания? Спасибо
Комментарии:
1. почему вы помещаете
trip
константу в квадратные скобки?const [trip] = snapshot.val();
Вы пытаетесь получить доступ к свойствуtrip
изsnapshot.val()
, напримерconst { trip } = snapshot.val();
2. Если я размещаю его так, как вы предлагаете, то я получаю необработанное предупреждение promiserejectionwarning: TypeError: не удается уничтожить свойство
trip
‘undefined’ или ‘null’. Но я подумал, что это правильный способ деконструировать объект firebase?3. это был просто вопрос, а не предложение
Можете ли вы отредактировать свой пост и написать ошибку:
it returns me this error and I am totally baffled
4. Готово, спасибо за совет. Зачем я это делаю? Когда я немного думаю об этом, если оно хранится как объект в firebase, то нет логики для доступа к нему через квадратные скобки, но теперь я еще больше запутался, почему отключение не определено.
5. Является ли
id
свойство вложенным свойством одногоtrip
объекта? Если нет, вы можете получить к нему доступ следующим образом:reference().child(id)
.once(‘значение’)`
Ответ №1:
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.log(queryResult) // Make note of the object shape here. Make sure there are actually results.
const trip = Object.values(queryResult)[0]
return trip;
};
Комментарии:
1. Он просто возвращает QueryResult как null, поэтому кажется, что ссылка на databse не подходит. Я также отредактировал код контроллера, который обслуживает ID и все, может быть, я чего-то там не хватает?
2. Похоже. orderByChild, .equalTo и limitToFirst создают проблему, и я не совсем понимаю, почему.
3.
:id
Параметр, который вы получаете из Express и передаете вgetSingle
, скорее всего, является строкой, аid
свойство trip в Firebase — это число. Это может привести к сбою вашегоequalTo
запроса, поскольку он не может найти элемент с id === «1». ПопробуйтеequalTo(parseInt(id, 10))
и посмотрите, решит ли это проблему.4. Да, это решило проблему с идентификатором, который, очевидно, был строкой. Но довольно странная вещь происходит после того, как мне пришлось обновить код для отправки
snapshot.val()
в массив trip, и отправленные элементы отлично отображаются в JSON до его отправки, но при отправке вложенные элементы внутри отображаются как [object Объект].5. Глубоко вложенные объекты JSON часто будут отображаться как [Object] или [object object] при входе в консоль с помощью console.log. Это нормально. Вы можете попробовать
console.log(JSON.stringify(trips, null, 2))
сериализовать объект и распечатать его в виде строки.
Ответ №2:
Может быть необработанное предупреждение promiserejectionwarning.
Обработайте свой снимок с помощью 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.log(post.id) if required
})
};
Комментарии:
1. Да, это выдает, UnhandledPromiseRejectionWarning Я отредактировал ошибку. Просматривал документацию firebase и попробовал некоторые варианты, подобные опубликованным вами, но по-прежнему выдает мне ту же ошибку.