0

I've been looking at different resources online trying to find a working solution for what I have and so far I think I'm kinda botching my typescript integration. I'd love to have some help in properly setting up my types for my hook.

I have a useUser() hook that dispatches actions to my reducer and also returns selectors back from my store. I've made some progress, but I'm starting to get in over my head a little bit.

the hook: useUser.ts

  • I'm not sure what I can place as the return for this hook. I tried placing useUserActionTypes but I don't think that makes any difference, especially since I'm not returning anything really beyond either getting an object (userData), or a number (totalPoints, totalWords) from the store.
  • I dont think I should be "returning" my dispatches, but it made typescript less upset
  • I can also just type in something like 'Dog' instead of FETCH_USER into my dispatch's type for example. Probably doesn't matter, but I think there should be a safeguard in there, right?
  • Pretty stumped with how to actually fix that error in the destructured return. I have a type called User that represents an object that my store will have for user, but ... that made no difference.
import { useSelector, useDispatch } from 'react-redux';
import axios from 'axios';
import { User } from '../reducers/user';

export const FETCH_USER = 'FETCH_USER';
export const UPDATE_ERRORS = 'UPDATE_ERRORS';
export const INCREMENT_POINTS = 'INCREMENT_POINTS';
export const INCREMENT_WORDS = 'INCREMENT_WORDS';

type Error = {
  code: number;
  message: string;
};

type FetchUserAction = {
  type: typeof FETCH_USER;
  payload: User;
};

type UpdateErrorsAction = {
  type: typeof UPDATE_ERRORS;
  payload: Error[];
};

type IncrementPointsAction = {
  type: typeof INCREMENT_POINTS;
  payload: number;
};

type IncrementWordsActions = {
  type: typeof INCREMENT_WORDS;
};

// ? Typescript is able to infer the correct type in the Union Type below
export type useUserActionTypes =
  | FetchUserAction
  | UpdateErrorsAction
  | IncrementPointsAction
  | IncrementWordsActions;

export type ReduxStore = {
  alert: any;
  user: User;
};

const useUser = (): useUserActionTypes => {
  const userData: User = useSelector((state: ReduxStore) => state.user);
  const totalPoints: number = useSelector(
    (state: ReduxStore) => state.user.points
  );
  const totalWords: number = useSelector(
    (state: ReduxStore) => state.user.words
  );
  const dispatch = useDispatch();
  const fetchUser = async (): Promise<FetchUserAction | UpdateErrorsAction> => {
    try {
      const response = await axios.get(
        'http://localhost:5000/api/v1/users/WhpHq4qWFdzlhlx2ztqD'
      );
      const user = response.data;
      return dispatch({
        type: FETCH_USER,
        payload: user,
      });
    } catch (error) {
      return dispatch({
        type: UPDATE_ERRORS,
        payload: [
          {
            code: 500,
            message: error.message,
          },
        ],
      });
    }
  };
  const incrementPoints = (amount: number): useUserActionTypes => {
    return dispatch({
      type: INCREMENT_POINTS,
      payload: amount,
    });
  };
  const incrementWords = (): useUserActionTypes => {
    return dispatch({
      type: INCREMENT_WORDS,
    });
  };
  return {
    userData,
    totalPoints,
    totalWords,
    fetchUser,
    incrementPoints,
    incrementWords,
  };
};

export default useUser;

enter image description here


On a page where I am trying to use the selectors:

  • I thought these were covered in my hook, I have types assigned to these constants.
  • fetchUser() returns a type of 'any' ... same issue as above perhaps?

enter image description here

enter image description here

Thank you for any help, It's definitely fun trying to get this all properly hooked up with typescript but I am a bit lost currently.

1
  • 1
    useUserActionTypes type is wrong type for useUser return, useUser was typed to return a single action (an object with type and payload keys) while it actually returns multiple things with fetchUser being action creator and not an action. Commented Aug 27, 2020 at 21:11

1 Answer 1

2

The problem is that you incorrectly typed useUser, the correct return type according to your code would be:

{
    userData: User;
    totalPoints: number;
    totalWords: number;
    fetchUser(): Promise<FetchUserAction | UpdateErrorsAction>;
    incrementPoints(amount: number): useUserActionTypes;
    incrementWords(): useUserActionTypes;
}

Playground

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.