When passing a date over the getServerSideProps boundary, it fails to serialize the Date object. Dates are serializable, so they should be allowed through.
Attempt to pass a date time through the API, like so
page/index.tsx
const Component = () => {
return <div>Hello</div>
}
export const getServerSideProps = async (ctx) => {
const d = new Date();
return { props: { d } }
}
export default Component
Serializing occurs just fine
See Stack Trace
While crude, to not have to write complex logic to determine serializability, you could replace the offending method with
const canSerialize = (obj) => {
try {
JSON.stringify(obj);
return false;
} catch (e) {
return false;
}
}
Stack Trade:
SerializableError: Error serializing `.user.lastLogin` returned from `getServerSideProps` in "/dashboard".
Reason: `object` ("[object Date]") cannot be serialized as JSON. Please only return JSON serializable data types.
at isSerializable (/Users/jake/programming/Railway/frontend/node_modules/next/dist/lib/is-serializable-props.js:9:7)
at /Users/jake/programming/Railway/frontend/node_modules/next/dist/lib/is-serializable-props.js:7:497
at Array.every (<anonymous>)
at isSerializable (/Users/jake/programming/Railway/frontend/node_modules/next/dist/lib/is-serializable-props.js:7:304)
at /Users/jake/programming/Railway/frontend/node_modules/next/dist/lib/is-serializable-props.js:7:497
at Array.every (<anonymous>)
at isSerializable (/Users/jake/programming/Railway/frontend/node_modules/next/dist/lib/is-serializable-props.js:7:304)
at Object.isSerializableProps (/Users/jake/programming/Railway/frontend/node_modules/next/dist/lib/is-serializable-props.js:9:219)
at Object.renderToHTML (/Users/jake/programming/Railway/frontend/node_modules/next/dist/next-server/server/render.js:356:42)
at runMicrotasks (<anonymous>)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at async DevServer.renderToHTMLWithComponents (/Users/jake/programming/Railway/frontend/node_modules/next/dist/next-server/server/next-server.js:660:26)
at async DevServer.renderToHTML (/Users/jake/programming/Railway/frontend/node_modules/next/dist/next-server/server/next-server.js:807:28)
at async DevServer.renderToHTML (/Users/jake/programming/Railway/frontend/node_modules/next/dist/server/next-dev-server.js:22:539)
at async DevServer.render (/Users/jake/programming/Railway/frontend/node_modules/next/dist/next-server/server/next-server.js:552:22)
at async Object.fn (/Users/jake/programming/Railway/frontend/node_modules/next/dist/next-server/server/next-server.js:402:17)
You have to cast to String first.
function replacer(key, value) {
if (typeof value === 'Date') {
return value.toString();
}
return value;
}
result = JSON.stringify(obj, replacer)
This check is necessary as we do not serialize props on the server for performance reasons. So, this check only runs in development and has you make things serializable with scalar types, meaning they'll match exact on the client.
I'm having this issue when fetching data from Contentful on posts that have links to each other.
Stringifying using safe-json-stringify and reparsing fixes, but I'm hoping there is a more performant solution.
import safeJsonStringify from 'safe-json-stringify';
...
export async function getServerSideProps({ params, preview = false }) {
const rawData = await getSlugPageProps(params.slug, 'product-page', preview);
const stringifiedData = safeJsonStringify(rawData);
const data = JSON.parse(stringifiedData);
return {
props: {
data
}
};
}
Most helpful comment
You have to cast to String first.