Home > OS >  React TS useContext and UseReducer with axios
React TS useContext and UseReducer with axios

Time:12-11

I am making an Axios call to get data. What should be the type for Axios call? For now, the type is any but how can I make it more strict?

import axios from "axios";
import { createContext, useEffect, useContext, useReducer } from "react";
import { Action, LevelsType, State, StateContextType, StateProviderPropsType } from "../Types/types";

const LevelCtx = createContext({} as StateContextType);

export function LevelProvider({children}:StateProviderPropsType) {

    const initialState:State = {
        levels: null
    }

    const [state, dispatch] = useReducer(reducer, initialState)

    useEffect(() => {
        (async () => {
           const response = await axios.get<any>("http://localhost:5000/levels"); // Fix required.

            return dispatch({type: "SET_LEVELS", payload: response.data.levels})
            

        })();
        
    }, [])


    function reducer(state:State, action: Action) {
        switch (action.type) {
            case "SET_LEVELS":
                return {...state, levels: action.payload }
        
            default:
                return state
        }
    }

    console.log("levelCTX", state);

    return (
        <LevelCtx.Provider value={{ state, dispatch }}>
            {children}
        </LevelCtx.Provider>
    )
};

export function useLevelCtx() {
    return useContext(LevelCtx);
}

My types file looks like this -

import { ReactNode }from "react";

export type LevelsObjectType = {
    _id: string;
    img: string;
    levelName: string;
    __v: number;
}

export type LevelsType = {
    levels: LevelsObjectType[]
}

export type State = {
    levels: LevelsType[] | null;
}

export type StateProviderPropsType = {
    children: ReactNode;
}

export type StateContextType = {
    state: State;
    dispatch: React.Dispatch<Action>;
}

export type Action = 
    | { type: "SET_LEVELS"; payload: LevelsType[] }

export type ServerError = {
    errorMessage: string;
}



The data I am getting from the api call is this - enter image description here

Now after doing this when i try to map over state.levels, it throw the following error -

enter image description here

I tried adding LevelsType to the above axios call but it is throwing an error. I am trying to setup useRecuder and useContext using React TS. I am new to typescript. So please help me figure out this.

CodePudding user response:

You could have two types:

export type LevelsObjectType = {
    _id: string;
    img: string;
    levelName: string;
    __v: number;
}

export type LevelsObjectTypeResult = {
    levelsObjects: LevelsObjectType[],
    success: boolean
}

And return:

await axios.get<LevelsObjectTypeResult>("http://localhost:5000/levels")

In the reducer:

 return {...state, levels: action.payload.levelsObjects }

CodePudding user response:

You are getting an error because of the way your State type is defined

export type State = {
    levels: LevelsType[] | null;
}

When you do state.levels.map(level), level type is LevelsType which you defined like this

export type LevelsType = {
    levels: LevelsObjectType[]
}

so you are trying to access _id on a LevelsType object and obviously typescript complains about it since _id doesn't exist in LevelsType.

Try this:

export type State = {
    levels: LevelsObjectType[] | null;
}
  • Related