I have two components Auth and Main, which represent the Login screen and the Main screen of the app. Both are called by component AuthOrApp, which chooses which one to display based on the user's state id.
//component AuthOrApp
import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { login } from '../store/userSlice';
import { addShops } from '../store/shopsSlice';
import Auth from '../screens/Auth';
import Main from '../navigators/Main';
import { getData } from '../common';
export default props => {
const [start, setStart] = useState(true);
const dispatch = useDispatch();
const user = useSelector(state => state.user);
const fetchData = async () => {
if (!user.id) {
const userData = await getData();
if (userData.id) {
dispatch(addShops(userData.filterShops));
dispatch(login({ name: userData.name, id: userData.id }));
} else {
setStart(false);
}
} else {
setStart(false);
}
}
useEffect(() => {
fetchData();
}, [user])
return (!user.id) ? <Auth /> : <Main />;
}
When logging out, the user state id is cleared and the app returns to the login screen. The problem is that it mounts the Auth and Main component again.
I don't understand why it reassembles the components instead of just rendering. Could someone explain it to me? How do I stop it from mounting again?
1. Render Both, Toggle Visibility
function AuthOrApp() {
const user = useSelector(state => state.user);
return (
<>
<Auth style={{ display: !user.id ? 'block' : 'none' }} />
<Main style={{ display: user.id ? 'block' : 'none' }} />
</>
);
}
1. Use React Router
npm install react-router-dom
// App.js or a central routing component
import React from 'react';
import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
import { useSelector } from 'react-redux';
import Auth from './screens/Auth';
import Main from './navigators/Main';
const App = () => {
const user = useSelector(state => state.user);
return (
<Router>
<Routes>
<Route
path="/login"
element={!user.id ? <Auth /> : <Navigate to="/main" />}
/>
<Route
path="/main"
element={user.id ? <Main /> : <Navigate to="/login" />}
/>
{/* Redirect any unknown routes */}
<Route
path="*"
element={<Navigate to={user.id ? "/main" : "/login"} />}
/>
</Routes>
</Router>
);
}
export default App;
// In your logout function/component
import { useDispatch } from 'react-redux';
import { logout } from '../store/userSlice';
import { useNavigate } from 'react-router-dom';
const LogoutButton = () => {
const dispatch = useDispatch();
const navigate = useNavigate();
const handleLogout = () => {
dispatch(logout()); // Clears user.id
navigate('/login'); // Redirects to login
};
return <button onClick={handleLogout}>Logout</button>;
};
If you want to preserve the state of a component even when it's unmounted (e.g., user partially filled a form on the Auth screen and doesn't want to lose that information upon navigating away), you can manage the state globally using Redux or React's Context API.