lester23
lester23

Reputation: 81

"No overload matches this call" error when setting up ContextApi & useReducer using Typescript in React

I'm new to typescript and I've been trying to setup createContext and useReducer. But I got the following error. Anyone who could shed some information or help would be much appreciated. enter image description here

No overload matches this call. Overload 1 of 5, '(reducer: ReducerWithoutAction, initializerArg: any, initializer?: undefined): [any, DispatchWithoutAction]', gave the following error. Argument of type '(state: WorkoutState, action: WorkoutAction) => { workouts: WorkoutState; } | { workouts: (WorkoutState | { _id: string; title: string; reps: number; load: number; createdAt: string; })[]; }' is not assignable to parameter of type 'ReducerWithoutAction'. Overload 2 of 5, '(reducer: (state: WorkoutState, action: WorkoutAction) => { workouts: WorkoutState; } | { workouts: (WorkoutState | { _id: string; title: string; reps: number; load: number; createdAt: string; })[]; }, initialState: never, initializer?: undefined): [...]', gave the following error. Argument of type '{ workouts: { _id: string; title: string; reps: number; load: number; createdAt: string; }[]; }' is not assignable to parameter of type 'never'.ts(2769)

import { createContext, ReactNode, useReducer } from "react";

interface WorkoutState {
  workouts: {
    _id: string;
    title: string;
    reps: number;
    load: number;
    createdAt: string;
  }[];
}

interface WorkoutAction {
  type: "GET_ALL_WORKOUTS" | "ADD_WORKOUT";
  payload: WorkoutState;
}

const initialState = {
  workouts: [
    {
      _id: "",
      title: "",
      reps: 0,
      load: 0,
      createdAt: "",
    },
  ],
};

export const WorkoutContext = createContext(initialState);

export const workoutReducer = (state: WorkoutState, action: WorkoutAction) => {
  switch (action.type) {
    case "GET_ALL_WORKOUTS":
      return {
        ...state,
      };
    case "ADD_WORKOUT":
      return {
        workouts: [...state.workouts, action.payload],
      };
    default:
      return state;
  }
};

export const WorkoutContextProvider = (children: ReactNode) => {
  const [state, dispatch] = useReducer(workoutReducer, initialState);
  return (
    <WorkoutContext.Provider value={state}>{children}</WorkoutContext.Provider>
  );
};

The error is from the useReducer. Thank you in advance

Upvotes: 2

Views: 792

Answers (1)

lester23
lester23

Reputation: 81

With much digging, I was able to run it,

I change my WorkoutState into type of initialState

type WorkoutState = typeof initialState;

then on the createContext, I passed an object with 2 parameters state:WorkoutState,dispatch:Dispatch then set the state:initialState and dispatch as an empty function

export const WorkoutContext = createContext<{
  state: WorkoutState;
  dispatch: Dispatch<WorkoutAction>;
}>({ state: initialState, dispatch: () => {} });

On the reducer, since the initialState is an object, It needs to return an object as well

In the ContextProvider I set the children:{children: ReactNode} then pass the state and dispatch into the value

export const WorkoutContextProvider = ({
  children,
}: {
  children: ReactNode;
}) => {
  const [state, dispatch] = useReducer(workoutReducer, initialState);
  return (
    <WorkoutContext.Provider value={{ state, dispatch }}>
      {children}
    </WorkoutContext.Provider>
  );
};

I hope this can help someone. (this will also remind me in the future.) :-)

Upvotes: 0

Related Questions