Axios Error Response Using TypeScript, React and React-Query - reactjs

I need to display the error message and if it has no error message just default it to an error status code. Problem right now is that it says Property 'message' does not exist on type 'MyErrorResponse'.
auth service
import { AxiosError } from 'axios'
import { useMutation } from 'react-query'
import { _axios, URL_TEMPLATES } from '../api'
export type LoginPayload = {
username: string;
password: string;
};
type LoginResponse = {
data: {
username: string;
email: string;
token: string;
};
};
type MyErrorResponse = {
errors: { detail: string }[];
};
export const useLogin = () => {
return useMutation<LoginResponse, AxiosError<MyErrorResponse>, LoginPayload>(
(payload) => _axios.post(URL_TEMPLATES.LOGIN, { ...payload })
)
}
component
const { mutate, error } = useLogin()
{error && (
<Typography variant='h6' sx={{ color: theme.palette.red, mt: 2 }}>
{error.response?.data.message}
</Typography>
)}

Your MyErrorResponse should be typed according what you return from the backend. In this case, it should be,
type MyErrorResponse = {
message: string
};
the hint is from the error you got, Property 'message' does not exist on type 'MyErrorResponse'. It's a typescript error that indicates you have invalid type.

Related

React Navigation custom route params and typescript

I have an Error screen that needs to know the error number and a description to display the error and I can't figure out how to tell TS which types are my Error screen custom params. I'm calling my Error screen this way.
navigation.dispatch(
StackActions.replace('Error', {
statusCode: 400,
description: 'Error description',
}),
);
This is my Error screen component. TS complains in route.params
export default function ErrorScreen({ route, navigation }: RootStackScreenProps<'Error'>) {
const { statusCode, description } = route.params; <-- TS error here
// #ts-ignore
const { setClientURL } = appState(({ setClientURL }) => ({
setClientURL,
}));
TS2339: Property 'description' does not exist on type 'Readonly {
key: string; index: number; routeNames: string[]; history?: unknown[]
| undefined; routes: NavigationRoute []; type: string; stale: false;
}>> | undefined>'.
These are my types definitions
import { NavigatorScreenParams } from '#react-navigation/native';
import { NativeStackScreenProps } from '#react-navigation/native-stack';
export type RootStackParamList = {
Root: undefined;
Error: NavigatorScreenParams<ErrorParamList> | undefined;
Notifications: undefined;
Log: undefined;
};
export type RootStackScreenProps<Screen extends keyof RootStackParamList> = NativeStackScreenProps<
RootStackParamList,
Screen
>;
export type ErrorParamList = {
Error: {
statusCode: number;
description: string;
};
};
This is my navigator create code
export default function Navigation({ colorScheme }: { colorScheme: ColorSchemeName }) {
return (
<NavigationContainer
linking={LinkingConfiguration}
theme={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
<RootNavigator />
</NavigationContainer>
);
}
/**
* A root stack navigator is often used for displaying modals on top of all other content.
* https://reactnavigation.org/docs/modal
*/
const Stack = createNativeStackNavigator<RootStackParamList>();
function RootNavigator() {
const colorScheme = useColorScheme();
return (
<Stack.Navigator>
<Stack.Screen
name="Error"
component={ErrorScreen}
options={({ navigation }: RootStackScreenProps<'Error'>) => ({
headerLeft: () => null,
title: 'Ups!...',
headerShadowVisible: false,
headerStyle: {
backgroundColor: '#ffe56d',
},
headerTitleStyle: {
fontWeight: 'bold',
fontSize: 30,
},
gestureEnabled: false,
headerBackVisible: false,
})}
/>
How can I tell TS that for my Error screen route.params can have statusCode and description primitives?

TS: custom onSubmit do not match React Hook Form types

I'm geting type's problems when I try to use SubmitHandler type to typping onSubmit prop, I'm getting:
TS2345: Argument of type 'SubmitHandler<T>' is not assignable to parameter of type 'SubmitHandler<FieldValues>'. Type 'FieldValues' is not assignable to type 'T'. 'T' could be instantiated with an arbitrary type which could be unrelated to 'FieldValues'.
Implementation
import { FieldValues, useFormContext, SubmitHandler } from 'react-hook-form';
import { Pressable, Text } from 'react-native';
type ButtonProps<T extends FieldValues> = PressableProps & {
onSubmit: SubmitHandler<T>;
};
function SubmitButton<T = FieldValues>({ onSubmit, ...RestButtonProps }: ButtonProps<T>) {
const { handleSubmit } = useFormContext();
return (
<Pressable {...RestButtonProps} onPress={() => handleSubmit(onSubmit)}>
<Text>Submit</Text>
</Pressable>
);
}
type LoginFormValues = {
email: string;
password: string;
};
function LoginForm() {
const handleSubmit: SubmitHandler<LoginFormValues> = ({ email, password }) =>
console.warn(email, password);
return (
<SubmitButton<LoginFormValues> title="Sign In" onSubmit={handleSubmit} />
);
}

Types error with AxiosResponse and UseQueryResult

I am using react query in my typescript project.
export type CarouselData = {
name: string;
body: string;
imgOne: string;
imgTwo: string;
};
export const getCarouselData = async (): Promise<
AxiosResponse<CarouselData[]>
> => {
return await (
await publicAPI.get('/carouselData')
);
};
export const useGetCarouselData = (): UseQueryResult<
Promise<AxiosResponse<CarouselData[]>>
> => {
return useQuery('getCarouselData', getCarouselData);
};
In my component, I am consuming this as follows.
type Item = {
name: string,
body: string,
imgOne: string,
imgTwo: string,
}
export const HomeCarousel: FC = () => {
const {Root} = useStyles();
const result = useGetCarouselData();
console.log(result.data.data); //data.data is giving an error
return (
<Root>
<Carousel<Item[]>>
{result.data.data.map((item, index)=> {
return <CarouselItem key={index} name={item.name} body={item.body} imgOne={item.imgOne} imgTwo={item.imgTwo}/>
})}
</Carousel>
</Root>
)
}
Now, I am getting an error Property 'data' does not exist on type 'Promise<AxiosResponse<CarouselData[], any>>'.ts(2339) that shouldn't be there?
I want to know why this is happening or how to resolve this. : )
Any help is appreciated.
react-query unwraps the Promise, so you'd want: UseQueryResult<AxiosResponse<CarouselData[]>>
Or, you can just use type inference. Leave out the type and let the compiler figure it out :)

how can i give type in getServerSideProps of Nextjs with typescript?

I'm using NextJs + TypeScript to make a little clone project, but I got a problem with type in getServerSideProps.
As you can see, in getServerSideProps, I am fetching data using with context.query.
But some error message is not fixed and I don't understand why that error appears.
The error message is this.
Type 'string[]' cannot be used as an index type.ts(2538)
Type 'undefined' cannot be used as an index type.ts(2538)
const genre: string | string[] | undefined
How can I fix this type problem?
import Head from "next/head";
import Nav from "../components/Nav/Nav";
import Header from "../components/Header/Header";
import Results from "../components/Results/Results";
import requests from "../utils/requests";
import { GetServerSideProps } from "next";
type HomeProps = {
results: {}[];
};
export default function Home({ results }: HomeProps) {
console.log(results);
return (
<div>
<Results results={results} />
</div>
);
}
export const getServerSideProps: GetServerSideProps = async (context) => {
const genre = context.query.genre
const response = await fetch(
`https://api.themoviedb.org/3${
requests[genre]?.url {/*this is problem line*/}
|| requests.fetchTopRated.url
}`
);
const data = await response.json();
return {
props: { results: data.results },
};
};
You can use like this;
type PageProps = {
isAuthanticated: boolean,
categories?: CategoryType[]
}
export const getServerSideProps: GetServerSideProps<PageProps> = async (context) => {
const _props: PageProps = {
isAuthanticated: auth,
categories: data.results
}
return { props: _props }
};
const Category: NextPage<PageProps> = (props) => {
return(
...
)
};
Since the type of genre can be string or string[] (or undefined), it can not be used to index requests without being narrowed down to string via the use of an if statement:
if (typeof genre === 'string') {
// Typescript now knows it is a string
const response = await fetch(
`https://api.themoviedb.org/3${
requests[genre]?.fetchTopRated.url {/*this is problem line*/}
|| requests.fetchTopRated.url
}`
);
const data = await response.json();
return {
props: { results: data.results },
};
} else if (typeof genre == 'object'){
// handle case where it is an array
} else {
// genre is undefined
}
When you receive params via context, the value could be either string or string[] (or undefined) so you need to cast. It could be a single genre or multiple genres in the URL.
?genre=film or ?genre=film&genre=music
For you case, simply cast as string:
const genre = context.query.genre as string;
UPDATE
As per your comments, the first issue that you raised in the question was actually about casting to string as above.
The second issue, which you should not actually be seeing and must be a TS or module config issue, is related to trying to accessing a key as string by index on your vanilla object exported from "../utils/requests";
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ fetchTrending: { title: string; url: string; }; ...
Your data object has literal key names:
// ../utils/requests
export default {
fetchTrending: {
title: "Trending",
url: /trending/all/week?api_key=${API_KEY}&language=en-US,
},
fetchTopRated: {
title: "Top Rated",
url: /movie/top_rated?api_key=${API_KEY}&language=en-US,
},
};
Rather define the type like this:
export interface IRequest {
[name: string]: {
title: string;
url: string;
};
}
const data: IRequest = {
fetchTrending: {
title: "Trending",
url: `/trending/all/week?api_key=${API_KEY}&language=en-US1`
},
fetchTopRated: {
title: "Top Rated",
url: `/movie/top_rated?api_key=${API_KEY}&language=en-US`
}
};
export default data;
or you could use a Record to have strongly typed keys:
type RequestNames = "fetchTrending" | "fetchTopRated";
export const records: Record<
RequestNames,
{
title: string;
url: string;
}
> = {
fetchTrending: {
title: "Trending",
url: `/trending/all/week?api_key=${API_KEY}&language=en-US1`
},
fetchTopRated: {
title: "Top Rated",
url: `/movie/top_rated?api_key=${API_KEY}&language=en-US`
}
};

Type '{ userId: string; }' has no properties in common with type 'AxiosRequestConfig'. | Axios - Next.js with typescript

( Hi comunnity ) I have this piece of code, everything was working fine, but got an error once i create the API.delete function, don't know what is going on there actually
import axios, { AxiosRequestConfig } from "axios";
const API = axios.create({ baseURL: "http://localhost:5000/api" });
// Set header for each request to give permission
API.interceptors.request.use((req: AxiosRequestConfig) => {
if (localStorage.getItem("Auth")) {
req.headers.Authorization = `Bearer ${
JSON.parse(localStorage.getItem("Auth")).token
}`;
}
return req;
});
// login - register - update perfil
export const login = (loginData: {
email: string | null;
password: string | null;
}) => API.post(`/user/login`, loginData);
export const register = (registerData: {
email: string;
password: string;
name: string;
}) => API.post("/user/register", registerData);
export const updatePerfilPhotos = (
photosBase64: { perfil?: string; banner?: string },
id: string
) => API.patch(`/user/update/${id}`, photosBase64);
export const AddNotification = (
userInformation: { userId: string },
id: string
) => API.patch(`/user/notification/${id}`, userInformation);
export const DeleteNotificationOrFriend = (
userInformation: { userId: string },
id: string
) => API.delete(`/user/deleteNotification/${id}`, userInformation);
//
In the API.delete function there's a problem :
(parameter) userInformation: {
userId: string;
}
Type '{ userId: string; }' has no properties in common with type 'AxiosRequestConfig'
What does that mean ? why is that happening, how can i fix this ?
Thanks for your time friends !
I think the delete method signature should be like this,
API.delete(`/user/deleteNotification/${id}`, { data: userInformation })
Refer: https://github.com/axios/axios/issues/897#issuecomment-343715381

Resources