I have a c# .net 8 backend (later known as BE) to provide my react typescript frontend (FE) with data.
I use RTK Query to fetch the data but I just ran into trouble when assuming that the Date object I got from BE was infact a Date object.
Class in BE:
public class Action
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime? StartDate { get; set; }
}
Type in FE:
export interface Action {
id: number;
name: string;
startDate: Date;
}
RTK Query endpoint:
actionById: builder.query<Action, number>({
query: (id: number) => ({
url: `${BASE_URL}/v1/Action/${id}`
method: 'GET',
}),
}),
Response from BE is obiviously a JSON String but I thought the conversion to Date object were made automatically. It was not. Everything worked fine until I tried to compare it with another date which failed.
So question is, how do I solve this in the best way?
I could change the type in FE to be startDate: string;
to avoid the confusion, but is there a better way?
Answers
To ensure that the Date object received from the backend is correctly parsed into a JavaScript Date object in your React TypeScript frontend, you have a few options:
-
Use Custom Serialization/Deserialization: You can define a custom serialization and deserialization logic for the Date objects between your backend and frontend. This involves converting the Date object to a string representation (e.g., ISO 8601 format) when sending it from the backend and parsing it back to a Date object in the frontend. This ensures consistent handling of Date objects between the two layers.
Backend (C#):
public class Action { public int Id { get; set; } public string Name { get; set; } public DateTime? StartDate { get; set; } public string StartDateAsString => StartDate?.ToString("yyyy-MM-ddTHH:mm:ss"); }
Frontend (TypeScript):
export interface Action { id: number; name: string; startDate: string; // Assuming the Date is serialized as a string }
-
Custom Transformation in RTK Query: You can define a custom transformation function in RTK Query to parse the Date string received from the backend into a JavaScript Date object. This allows you to keep the Date type in your TypeScript interface.
Frontend (TypeScript):
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; const api = createApi({ reducerPath: 'api', baseQuery: fetchBaseQuery({ baseUrl: '/api' }), endpoints: (builder) => ({ actionById: builder.query<Action, number>({ query: (id: number) => ({ url: `/v1/Action/${id}`, method: 'GET', }), transformResponse: (response: any) => ({ id: response.id, name: response.name, startDate: new Date(response.startDate), }), }), }), }); export const { useActionByIdQuery } = api;
Using either of these approaches will ensure that the Date objects received from the backend are correctly parsed into JavaScript Date objects in your React TypeScript frontend, allowing you to work with them seamlessly.