Private Route in react redux firebase not working

Viewed 524

I been trying to integrate the react-redux-firebase with my react app. Everything is working except for the protected routes

I copied the code for private route from react-react-firebase.

This is the code for my private route

import React from "react";
import { Route, Redirect } from "react-router-dom";
import { useSelector } from "react-redux";
import { isLoaded, isEmpty } from "react-redux-firebase";

// A wrapper for <Route> that redirects to the login
// screen if you're not yet authenticated or if auth is not
// yet loaded
function PrivateRoute({ children, ...rest }) {
  // FIXME: #27 Imp This is not working for some reason, you can still access the not accessible locations
  const auth = useSelector((state) => state.firebase.auth);
  console.log(auth);
  console.log("Empty?");
  console.log(isEmpty(auth));
  console.log("Load?");
  console.log(isLoaded(auth));
  return (
    <Route
      {...rest}
      render={({ location }) =>
        // FIXME: Here it even if it is false it is rendering the children for some reason
        isLoaded(auth) && !isEmpty(auth) ? (
          // auth.uid==undefined ? ( // Even this does not work
          children
        ) : (
          <Redirect
            to={{
              pathname: "/redirect/login",
              state: { from: location },
            }}
          />
        )
      }
    />
  );
}

export default PrivateRoute;

Even when the isEmpty is false, it is returning the children.

This is my reducer code.

import { combineReducers } from "redux";
import { firebaseReducer } from "react-redux-firebase";

export default combineReducers({
  firebase: firebaseReducer,

  // authReducer,
  // apiStatusReducer,
});

I been trying to solve it for the past 1 week and would love any help or hints on why it isn't working. Thanks for the help.

Edit:-

For some weird reason, even exchanging the children and redirect positions is also working.

<Route
      {...rest}
      render={({ location }) =>
        // FIXME: Here it even if it is false it is rendering the children for some reason
        isLoaded(auth) && isEmpty(auth) ? (
          // auth.uid==undefined ? ( // Even this does not work
          <Redirect
            to={{
              pathname: "/redirect/login",
              state: { from: location },
            }}
          />
        ) : (
          children
        )
      }
    />
2 Answers

This is an open issue in the react-redux-firebase repo(Link to Issue) as of 16 Sept 2020. There is an ugly workaround for this issue provided by @zachlyoung

Normally, we would login in this way:

firebase.login(credentials).then(() => {
  props.history.push("/dashboard"); // Private Route
});

Instead of directly going to the private route, we update the auth again.

firebase.login(credentials).then(() => {
  firebase.reloadAuth().then(() => {
    props.history.push("/dashboard"); // Private Route
  });
});

you need to change the condition to be like this:

isLoaded(auth) && !isEmpty(auth)

because when the isLoaded is false, isEmpty will be true and when isLoaded is true, the isEmpty will be false, that's why your condition always applies the second expression.

Related