Lola
Lola

Reputation: 145

useSelector doesn't load the state in time

I'm working on a project of mine using React and Redux.

I'm trying to retrieve the token field from my auth state from my store (which contains an authentication key that I intend to send over to my server side) using useSelectorbut the thing is, that it doesn't load in time. How do I fix this?

I'll add below parts of my code that are associated with this issue:

LikeButton.js: (here is the part where I'm trying to retrieve token)

...

const LikeButton = ({ postId }) => {
  const classes = useStyles();
  const [isLiked, setIsLiked] = useState(false);
  const isMount = useIsMount();
  const dispatch = useDispatch();
  const { token } = useSelector((state) => state.auth);
  const { likedPostsIds } = useSelector((state) => state.likes);

  useEffect(() => {
    if (token) dispatch(fetchLikedPosts(token));
  }, [token]);

...

likeActions.js:

...

export const fetchLikedPosts = ({ token }) => (dispatch) => {
  fetch("http://localhost:8080/graphql", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${token}`,
      "Content-Type": "application/json",
    },
    body: fetchLikedPostsQuery(),
  })
    .then((res) => res.json())

...

authActions.js

...

export const signIn = ({ password, email }) => (dispatch) => {
  dispatch({
    type: IS_AUTH_LOADING,
  });
  fetch("http://localhost:8080/graphql", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: signInQuery(password, email),
  })
    .then((res) => res.json())
    .then((resData) => {
      if (resData.errors) {
        dispatch(showNotification("User authentication has failed!", ERROR));
        dispatch({
          type: AUTH_ERROR,
        });
      } else {
        setLocalStorageAuth(resData.data.signIn.token, expiryDate);
        dispatch({
          type: SIGN_IN,
          payload: resData.data.signIn,
        });
      }
    })
    .catch((err) => {
      dispatch(
        showNotification(
          "User authentication has failed. Please try again later.",
          ERROR
        )
      );
      dispatch({
        type: AUTH_ERROR,
      });
      emptyLocalStorage();
    });
};
...

auth.js:

...

const initialState = {
  token: localStorage.getItem("token"),
  isAuth: localStorage.getItem("isAuth"),
  expiryDate: localStorage.getItem("expiryDate"),
  isLoading: false,
};

export default function authReducer(state = initialState, action) {
  switch (action.type) {
    case REGISTER_LOADING:
    case IS_AUTH_LOADING:
      return {
        ...state,
        isLoading: true,
      };
    case SIGN_IN:
      return {
        token: action.payload.token,
        isAuth: true,
        isLoading: false,
      };
    case AUTH_ERROR:
    case LOGIN_FAIL:
    case REGISTER_FAIL:
    case LOGOUT_SUCCESS:
      return {
        token: null,
        isAuth: false,
        isLoading: false,
      };
    case CREATE_USER:
      return {
        ...state,
        isLoading: false,
      };
    default:
      return state;
  }
}

...

Upvotes: 0

Views: 1081

Answers (1)

azundo
azundo

Reputation: 6052

The fetchLikedPosts function expects an object with a token key as an argument. the effect currently passes just the token as an argument. Try

  useEffect(() => {
     // note the change from token to {token}
    if (token) dispatch(fetchLikedPosts({token}));
  }, [token]);

Upvotes: 1

Related Questions