Manoj Sethi
Manoj Sethi

Reputation: 2028

React Redux with Typescript, Property Not Available in Reducer from ActionType

I am learning React with typescript and is currently facing problem while implementing Reducer in Redux.

These are my action types

import { LoginResponseInterface } from "../../interfaces/APIResponseInterface";

export const UserActionConst = {
  LOGIN_REQUEST: "USER_LOGIN_REQUEST",
  LOGIN_SUCCESS: "USER_LOGIN_REQUEST",
  LOGIN_FALIURE: "USER_LOGIN_REQUEST",

  LOGOUT: "USER_LOGOUT",
};

export interface LoginRequestAction {
  type: typeof UserActionConst.LOGIN_REQUEST;
}

export interface LoginSuccessAction {
  type: typeof UserActionConst.LOGIN_SUCCESS;
  payload: LoginResponseInterface;
}

export interface LoginFaliureAction {
  type: typeof UserActionConst.LOGIN_FALIURE;
}

export type UserActionsTypes =
  | LoginRequestAction
  | LoginSuccessAction
  | LoginFaliureAction;

And below is my reducer code

const initialState: IUserState = {
  isLoading: false,
  isLoggedIn: false,
  loggedInResponse: undefined,
};
export const userReducer = (
  state: IUserState = initialState,
  action: UserActionsTypes
): IUserState => {
  switch (action.type) {
    case UserActionConst.LOGIN_REQUEST:
      return { ...state, isLoading: true };
    case UserActionConst.LOGIN_SUCCESS:
      return {
        ...state,
        isLoading: false,
        isLoggedIn: true,
        loggedInResponse: action.payload,
      };
    default:
      return state;
  }
};

In this reducer my action type is UserActionType but when I try to access the property payload it's not available in IntelliSense and compiler complains about it. I am attaching a screenshot of the same.

If I try to use that type on a constant then the payload is available. Can you kindly help me identifying the issue with my reducer?

Property Not Available

Upvotes: 0

Views: 74

Answers (2)

Asaf Aviv
Asaf Aviv

Reputation: 11760

All of your actions constants have the same string so typescript can't separate the interfaces.

You need to define different action type names and add as const to the object containing the constants

export const UserActionConst = {
  LOGIN_REQUEST: "USER_LOGIN_REQUEST",
  LOGIN_SUCCESS: "USER_LOGIN_REQUEST_SUCCESS",
  LOGIN_FALIURE: "USER_LOGIN_REQUEST_FAILURE",
} as const

Another option is the make it an enum

export enum UserActionConst {
  LOGIN_REQUEST = "USER_LOGIN_REQUEST",
  LOGIN_SUCCESS = "USER_LOGIN_REQUEST_SUCCESS",
  LOGIN_FALIURE = "USER_LOGIN_REQUEST_FAILURE",
}

Upvotes: 1

SILENT
SILENT

Reputation: 4258

Its been a while since I've used redux but you are missing the action creators.

export const LoginRequest = () => ({
  type: UserActionConst.LOGIN_REQUEST,
})

export const LoginSuccess = (payload: LoginResponseInterface) => ({
  type: UserActionConst.LOGIN_SUCCESS,
  payload,
})

export const LoginFaliure = () => ({
  type: UserActionConst.LOGIN_FALIURE,
})

I also recommend you use React's useContext instead of redux. Does the same thing but its built into React.

Upvotes: 0

Related Questions