Error serializing `.meetups[0].title` returned from `getStaticProps` in "/" ` [duplicate] - mongodb

This question already has answers here:
Error serializing `.remarkBody` returned from `getStaticProps` . Reason: `undefined` cannot be serialized as JSON
(2 answers)
Closed 11 months ago.
I'm using next js with MongoDB, I'm getting the error serializing when submitting the form
error
Server Error
Error: Error serializing .meetups[0].title returned from getStaticProps in "/".
Reason: undefined cannot be serialized as JSON. Please use null or omit this value.
function HomePage(props){
return <MeetupList meetup={props.meetups} ></MeetupList>
}
export async function getStaticProps(){
const client = await MongoClient.connect("mongodb+srv://User:Password#cluster0.random.mongodb.net/meetups?retryWrites=true&w=majority");
const db = client.db();
const meetupsCollection = db.collection("meetups");
const meetups = await meetupsCollection.find().toArray();
client.close();
return {
props: {
meetups : meetups.map(meetup =>( {
title: meetup.title ,
address: meetup.address ,
source: meetup.source ,
id : meetup._id.toString()
}))
},
revalidate: 1
};
}
export default HomePage;

you should wrap the meetups prop value with JSON.stringify, see below:
return {
props: {
meetups: JSON.parse(
JSON.stringify(
meetups.map((meetup) => ({
title: meetup.title,
address: meetup.address,
source: meetup.source,
id: meetup._id.toString(),
}))
)
),
},
revalidate: 1,
};

Related

Redux Toolkit - do not send request when query param is invalid

I've checked the redux toolkit docs and don't see an example of this typical use case: do not send the request of the query has an invalid param.
For example, a get request to endpoint /categories/{name} requires a name value. If name does not have a value, then the request should not be made.
const baseQuery = fetchBaseQuery({
baseUrl: Constants.PATHWAY_API_URL
});
export const pathwayApi = createApi({
reducerPath: 'pathwayApi',
baseQuery: baseQueryWithReAuth,
endpoints: builder => ({
getSubCategories: builder.query({
// NETWORK REQUEST SHOULD NOT BE MADE IF "name" param is falsy
query: name => `${Constants.PATHWAY_API.CATEGORIES_PATH_NAME}/${name}`,
}),
}),
});
I want to add this type of param validation to all my queries that require a param value or values. What's the recommended approach / pattern for handling this validation at the createApi (or possibly fetchBaseQuery) layer?
Thanks in advance!
You can actually throw an error in your query function.
export const pathwayApi = createApi({
reducerPath: "pathwayApi",
baseQuery: baseQueryWithReAuth,
endpoints: (builder) => ({
getSubCategories: builder.query({
// NETWORK REQUEST SHOULD NOT BE MADE IF "name" param is falsy
query: (name) => {
if (!name) {
throw new Error("Category name is required.");
}
return `${Constants.PATHWAY_API.CATEGORIES_PATH_NAME}/${name}`;
}
})
})
});
When this happens, your hook will have isError: true but no network request will be made. The error property of your hook will be a SerializedError object with properties name, message and stack, which you can use to display the error in your UI.
This is the same type of error object that you get if you have a TypeError somewhere in your code. Note that JavaScript errors will have error.message while API errors (FetchBaseQueryError) will have error.error.
const Category = ({ name }) => {
const { data, error, isError } = useGetSubCategoriesQuery(name);
return (
<div>
<h3>Name: "{name}"</h3>
{isError && (
<div>{error?.error ?? error?.message}</div>
)}
</div>
);
};
CodeSandbox Link

Redux Toolkit Query: Reduce state from "mutation" response

Let's say I have an RESTish API to manage "posts".
GET /posts returns all posts
PATCH /posts:id updates a post and responds with new record data
I can implement this using RTK query via something like this:
const TAG_TYPE = 'POST';
// Define a service using a base URL and expected endpoints
export const postsApi = createApi({
reducerPath: 'postsApi',
tagTypes: [TAG_TYPE],
baseQuery,
endpoints: (builder) => ({
getPosts: builder.query<Form[], string>({
query: () => `/posts`,
providesTags: (result) =>
[
{ type: TAG_TYPE, id: 'LIST' },
],
}),
updatePost: builder.mutation<any, { formId: string; formData: any }>({
// note: an optional `queryFn` may be used in place of `query`
query: (data) => ({
url: `/post/${data.formId}`,
method: 'PATCH',
body: data.formData,
}),
// this causes a full re-query.
// Would be more efficient to update state based on resp.body
invalidatesTags: [{ type: TAG_TYPE, id: 'LIST' }],
}),
}),
});
When updatePost runs, it invalidates the LIST tag which causes getPosts to run again.
However, since the PATCH operation responds with the new data itself, I would like to avoid making an additional server request and instead just update my reducer state for that specific record with the content of response.body.
Seems like a common use case, but I'm struggling to find any documentation on doing something like this.
You can apply the mechanism described in optimistic updates, just a little bit later:
import { createApi, fetchBaseQuery } from '#reduxjs/toolkit/query'
import { Post } from './types'
const api = createApi({
// ...
endpoints: (build) => ({
// ...
updatePost: build.mutation<void, Pick<Post, 'id'> & Partial<Post>>({
query: ({ id, ...patch }) => ({
// ...
}),
async onQueryStarted({ id, ...patch }, { dispatch, queryFulfilled }) {
const { data } = await queryFulfilled
dispatch(
api.util.updateQueryData('getPost', id, (draft) => {
Object.assign(draft, data)
})
)
},
}),
}),
})

Serverless Framework and DynamoDB: Unexpected token in JSON at JSON.parse

Hi I followed this Serverless + AWS REST API tutorial and it went great, I got it to work.
Now, I'm trying to modify it but have hit a wall while trying to submit data into the DynamoDB table.
Using Postman to submit a valid JSON object I get a 502 response. If I test the function in Lambda, I get the following error:
{
"errorType": "SyntaxError",
"errorMessage": "Unexpected token o in JSON at position 1",
"trace": [
"SyntaxError: Unexpected token o in JSON at position 1",
" at JSON.parse (<anonymous>)",
" at Runtime.module.exports.submit [as handler] (/var/task/api/interview.js:11:28)",
" at Runtime.handleOnce (/var/runtime/Runtime.js:66:25)",
" at process._tickCallback (internal/process/next_tick.js:68:7)"
]
}
After searching for solutions, what I found out is that it seem like the event that is being passed as JSON.parse(event)is undefined.
Here's the serverless.yml:
service: interview
frameworkVersion: ">=1.1.0 <2.0.0"
provider:
name: aws
runtime: nodejs10.x
stage: dev
region: us-east-1
environment:
INTERVIEW_TABLE: ${self:service}-${opt:stage, self:provider.stage}
INTERVIEW_EMAIL_TABLE: "interview-email-${opt:stage, self:provider.stage}"
iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:Query
- dynamodb:Scan
- dynamodb:GetItem
- dynamodb:PutItem
Resource: "*"
resources:
Resources:
CandidatesDynamoDbTable:
Type: 'AWS::DynamoDB::Table'
DeletionPolicy: Retain
Properties:
AttributeDefinitions:
-
AttributeName: "id"
AttributeType: "S"
KeySchema:
-
AttributeName: "id"
KeyType: "HASH"
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
StreamSpecification:
StreamViewType: "NEW_AND_OLD_IMAGES"
TableName: ${self:provider.environment.INTERVIEW_TABLE}
functions:
interviewSubmission:
handler: api/interview.submit
memorySize: 128
description: Submit interview information and starts interview process.
events:
- http:
path: interviews
method: post
and the interview.js
'use strict';
const uuid = require('uuid');
const AWS = require('aws-sdk');
AWS.config.setPromisesDependency(require('bluebird'));
const dynamoDb = new AWS.DynamoDB.DocumentClient();
module.exports.submit = (event, context, callback) => {
const requestBody = JSON.parse(event);
const fullname = requestBody.fullname;
const email = requestBody.email;
const test = requestBody.test;
const experience = requestBody.experience;
if (typeof fullname !== 'string' || typeof email !== 'string' || typeof experience !== 'number') {
console.error('Validation Failed');
callback(new Error('Couldn\'t submit interview because of validation errors.'));
return;
}
submitInterviewP(interviewInfo(fullname, email, experience, test))
.then(res => {
callback(null, {
statusCode: 200,
body: JSON.stringify({
message: `Sucessfully submitted interview with email ${email}`,
interviewId: res.id
})
});
})
.catch(err => {
console.log(err);
callback(null, {
statusCode: 500,
body: JSON.stringify({
message: `Unable to submit interview with email ${email}`
})
})
});
};
const submitInterviewP = interview => {
console.log('Submitting interview');
const interviewInfo = {
TableName: process.env.INTERVIEW_TABLE,
Item: interview,
};
return dynamoDb.put(interviewInfo).promise()
.then(res => interview);
};
const interviewInfo = (fullname, email, experience,test) => {
const timestamp = new Date().getTime();
return {
id: uuid.v1(),
fullname: fullname,
email: email,
experience: experience,
test: test,
submittedAt: timestamp,
updatedAt: timestamp,
};
};
If I replace the event param for a valid JSON object and then deploy again. I'm able to successfully insert the object into dynamoDB.
Any clues? Please let me know if there's anything I missing that could help.
Thanks!
API Gateway stringify the request body in event's body property.
Currently you are trying to parse event object const requestBody = JSON.parse(event); which is wrong. You need to parse event.body property:
const requestBody = JSON.parse(event.body);

graphql-compose-mongoose generating an error: Expected [object Object] to be a GraphQL schema

I'm new to graphql-compose
I'm trying to launch a first service on a simple mongoose schema:
graphql.js :
import mongoose from 'mongoose'
import { composeWithMongoose} from 'graphql-compose-mongoose'
import { schemaComposer } from 'graphql-compose'
const db = require( '../models/db' )
//const mongoose = require('mongoose');
const folderDAO = mongoose.model('folder');
const customizationOptions = {}; // left it empty for simplicity, described below
const folderTC = composeWithMongoose(folderDAO, customizationOptions);
schemaComposer.rootQuery().addFields({
folderOne: folderTC.getResolver('findOne'),
})
const graphqlSchema = schemaComposer.buildSchema()
console.log("Schema built : ", graphqlSchema )
export default graphqlSchema
Now in my server code, I have this:
const express = require('express');
const graphqlHTTP = require('express-graphql')
const GraphQLSchema = require('./app_api/routes/graphql')
app.use('/graphql', graphqlHTTP({
schema: GraphQLSchema,
graphiql: true,
formatError: error => ({
message: error.message,
locations: error.locations,
stack: error.stack ? error.stack.split('\n') : [],
path: error.path
})
}));
On graphiql, when I attempt the following query:
{
folderOne(filter: {}, sort: _ID_ASC) {
name
}
}
I get the following error:
{
"errors": [
{
"message": "Expected [object Object] to be a GraphQL schema.",
"stack": [
"Error: Expected [object Object] to be a GraphQL schema.",
" at invariant (/Users/zied/work/share_place/node_modules/graphql/jsutils/invariant.js:19:11)",
" at validateSchema (/Users/zied/work/share_place/node_modules/graphql/type/validate.js:55:60)",
" at assertValidSchema (/Users/zied/work/share_place/node_modules/graphql/type/validate.js:80:16)",
" at validate (/Users/zied/work/share_place/node_modules/graphql/validation/validate.js:58:35)",
" at /Users/zied/work/share_place/node_modules/express-graphql/dist/index.js:139:52",
" at <anonymous>",
" at process._tickDomainCallback (internal/process/next_tick.js:228:7)"
]
}
]
}
What could I be missing???
p.s: sorry I attempted to tag the question with graphql-compose-mongoose but the tag doesn't exist, so I tagged it with graphql-js
Actually the issue was here:
const GraphQLSchema = require('./app_api/routes/graphql')
has to be replaced with
const GraphQLSchema = require('./app_api/routes/graphql').default
since we exported it as default
More info can be found here: https://github.com/graphql-compose/graphql-compose-mongoose/issues/103

facebook messenger bot encoding error

I have written sample echo message bot using facebook messenger api and wit.ai actions.
My message from facebook page is received and the proper action function defined using wit api's is also getting called. However
while returning the response, i am getting followin error as -
Oops! An error occurred while forwarding the response to : Error: (#100) Param message[text] must be a UTF-8 encoded string
at fetch.then.then.json (/app/index.js:106:13)
at process._tickCallback (internal/process/next_tick.js:103:7)
Here is the function which is used to return the response -
const fbMessage = (id, text) => {
const body = JSON.stringify({
recipient: { id },
message: { text },
});
const qs = 'access_token=' + encodeURIComponent(FB_PAGE_ACCESS_TOKEN);
return fetch('https://graph.facebook.com/v2.6/me/messages?' + qs, {
method: 'POST',
headers: {'Content-Type': 'application/json; charset=UTF-8'},
body
})
.then(rsp => rsp.json())
.then(json => {
if (json.error && json.error.message) {
throw new Error(json.error.message);`enter code here`
}
return json;
});
};
I have copied this function from the messenger.js file from the documentation since i am just trying the POC.
I checked the values for text and id in this function and verified using console.log statements and those are coming properly.
Can some experts help me to solve this error?
Note - I tried encoding the text using text.toString("utf8"); but it returns the encoding string as [object object] and thats the
response i get from bot. so it doesnt work.
Get the latest code from node-wit, there is a change in facebook id usage,
According to Facebook:
On Tue May 17 format of user and page ids delivered via webhooks will
change from an int to a string to better support default json encoder
in js (that trims long ints). Please make sure your app works with
string ids returned from webhooks as well as with ints.
Still you are getting issue with the api try to add if(event.message && !event.message.is_echo) condition as shown in below code.
// Message handler
app.post('/webhook', (req, res) => {
const data = req.body;
if (data.object === 'page') {
data.entry.forEach(entry => {
entry.messaging.forEach(event => {
if (event.message && !event.message.is_echo) {
const sender = event.sender.id;
const sessionId = findOrCreateSession(sender);
const {text, attachments} = event.message;
if (attachments) {
fbMessage(sender, 'Sorry I can only process text messages for now.')
.catch(console.error);
} else if (text) {
wit.runActions(
sessionId, // the user's current session
text, // the user's message
sessions[sessionId].context // the user's current session state
).then((context) => {
console.log('Waiting for next user messages');
sessions[sessionId].context = context;
})
.catch((err) => {
console.error('Oops! Got an error from Wit: ', err.stack || err);
})
}
} else {
console.log('received event', JSON.stringify(event));
}
});
});
}
res.sendStatus(200);
});
Reference:
no matching user bug
no matching user fix