I am using Typescript in my React app where I am also using Redux Toolkit for state management. The data is coming from Express Api and everything works perfectly if I implement Redux without Typescript but if I use Typescript I get this error:
ERROR in src/features/product/productSlice.tsx:61:27
TS2571: Object is of type 'unknown'.
59 | return data;
60 | } catch ( error ) {
> 61 | const message = ( error.response && error.response.data && error.response.data.message ) || error.message || error.toString();
| ^^^^^
62 | return thunkAPI.rejectWithValue( message );
63 | }
64 | } );
Now I am really new to Typescript as well as Redux Toolkit and I don't know how it fix it.
I am just making a get request in thunk function to fetch data at page load.
This is how productsSlice.tsx file looks like:
import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit';
import { RootState, AppThunk } from '../../app/store';
import getAllProducts from './productService';
interface Specifications {
display: string,
processor: string,
frontCam: string,
rearCam: string,
ram: string,
storage: string,
batteryCapacity: string,
os: string;
}
interface Products {
title: string,
slug: string,
description: string,
color: string,
price: number,
image: string,
specifications: Specifications;
};
export interface Data {
success: boolean;
message: string;
data: Products[] | null;
}
interface ProductState {
products: Products[] | null,
isError: boolean;
isSuccess: boolean;
isLoading: boolean;
message: string;
}
const initialState: ProductState = {
products: null,
isError: false,
isSuccess: false,
isLoading: false,
message: ''
};
export const getProducts = createAsyncThunk( 'products/getAllProducts', async ( _, thunkAPI ) => {
try {
const data = await getAllProducts();
return data;
} catch ( error ) {
const message = ( error.response && error.response.data && error.response.data.message ) || error.message || error.toString();
return thunkAPI.rejectWithValue( message );
}
} );
export const productSlice = createSlice( {
name: 'products',
initialState,
reducers: {},
extraReducers: ( builder ) => {
builder
.addCase( getProducts.pending, ( state ) => {
state.isLoading = true;
} )
.addCase( getProducts.fulfilled, ( state, action ) => {
state.isLoading = false;
state.isSuccess = true;
state.products = action.payload.data;
} )
.addCase( getProducts.rejected, ( state, action ) => {
state.isLoading = false;
state.isError = true;
state.message = action.payload;
state.products = null;
} );
}
} );
export const getProductsSelector = ( state: RootState ) => state.products;
export default productSlice.reducer;
This is productService.tsx:
import axios from 'axios';
import { Data } from './productSlice';
const API_URL: string = '/api/phones';
const getAllProducts = async (): Promise<Data> => {
const response = await axios.get( API_URL );
return response.data;
};
export default getAllProducts;
And this is the store:
import { configureStore, ThunkAction, Action } from '@reduxjs/toolkit';
import products from '../features/product/productSlice';
export const store = configureStore( {
reducer: {
products
},
} );
export type AppDispatch = typeof store.dispatch;
export type RootState = ReturnType<typeof store.getState>;
export type AppThunk<ReturnType = void> = ThunkAction<
ReturnType,
RootState,
unknown,
Action<string>
>;