0

I want to create a login form and a registration form on a separate page. I'm using useNavigate() and a context to navigate the user to the Main page when they've been logged in. But the user can't go to the registration page because if (!user) history('/'); doesn't let do it. How can I fix this so that an user can register on the Registration page and when the user is already logged in then stay on the Main page? Thank you.

App.js:

function App() {
    return (
        <div style={{fontFamily: 'Avenir'}}>
            <Router>
                <AuthProvider>
                    <Routes>
                        <Route path="/main" element={<Main/>}/>
                        <Route path="/" element={<Login/>}/>
                    </Routes>
                </AuthProvider>
                <Routes>
                    <Route path="/registration" element={<Registration/>}/>
                </Routes>
            </Router>
        </div>
    );
}

AuthContext.js:

const AuthContext = React.createContext();

export const AuthProvider = ({children}) => {
    const [loading, setLoading] = useState(true);
    const [user, setUser] = useState(null);
    const history = useNavigate();

    useEffect(() => {
        onAuthStateChanged(app, (user) => {
            setUser(user);
            setLoading(false);
            if (user) history('/main');
            if (!user) history('/');
        })
    }, [user, history]);

    const value = {user};

    return (
        <AuthContext.Provider value={value}>
            {!loading && children}
        </AuthContext.Provider>
    );
}

Login.js:

export function Login() {
     //...
     return( 
    //...
    <a href="/registration"><h2>Registration</h2></a>
    );
}
human758
  • 1
  • 1
  • Remove `if (!user) history('/');` – Konrad Oct 01 '22 at 16:19
  • If I remove this, the user will be able to go to the `Main` page even if they are not logged in. – human758 Oct 01 '22 at 17:40
  • Check what page user is trying to access and redirect conditionally. – Konrad Oct 01 '22 at 17:41
  • `if(!user) history('/');` prevents users (if they are not logged in) going to the `Main` page. And on the `Main` page there is `signOut` function and it does not work if `if (!user) history('/');` is deleted – human758 Oct 01 '22 at 17:56
  • The main purpose is `if(!user)` to redirect the user to `"/"` and the user should only be able to access the `"/registration"` page – human758 Oct 01 '22 at 18:08

1 Answers1

0

Only load the auth provider if the user is on a screen which requires auth. You'll need to import Switch from react-router for this.

function App() {
    return (
        <div style={{fontFamily: 'Avenir'}}>
            <Router>
                <Switch>
            
                    <Route exact path="/registration" element={<Registration/>}/>
                    <Route path="/" component={AuthProvider}>
                        <Routes>
                            <Route path="/main" element={<Main/>}/>
                            <Route path="/" element={<Login/>}/>
                        </Routes>
                    </Route>
                </Switch>
            </Router>
        </div>
    );
}
adsy
  • 8,531
  • 2
  • 20
  • 31
  • This doesn't work and throws an exception `No routes matched location "/"` – human758 Oct 01 '22 at 17:44
  • Ah try changing the route that has the provider component attached to “/*” – adsy Oct 01 '22 at 18:02
  • I also can’t remember if you need the “routes” nesting in the inner section. It’s on the right track though – adsy Oct 01 '22 at 18:04
  • And also it throws `[AuthProvider] is not a component. All component children of must be a or `. – human758 Oct 01 '22 at 18:30
  • Hmm perhaps try `element={}`? Apologies for my unsureness here, they recently upgraded react-router and Im still on the old API. The general pattern is what you want though -- you dont want to load the provider on pages that dont need it. – adsy Oct 01 '22 at 21:18
  • This, https://stackoverflow.com/questions/69864165/error-privateroute-is-not-a-route-component-all-component-children-of-rou appears to be the new way of dealing with providers as route components in the new API – adsy Oct 01 '22 at 21:21
  • If your able to share a cut down codesandbox of it, I can probably debug my way through it – adsy Oct 01 '22 at 21:23