I am working on a react application.
I am trying to create login and register functionality.
I have a Authorized.tsx
component which looks like this
export const Authorized = (props: authorizedProps) => {
const [isAuthorized, setIsAuthorized] = useState(true);
const { claims } = useContext(AuthContext);
useEffect(() => {
if (props.role) {
const index = claims.findIndex(
claim => claim.name === 'role' && claim.value === props.role)
setIsAuthorized(index > -1);
} else {
setIsAuthorized(claims.length > 0);
}
}, [claims, props.role]);
return (
<>
{isAuthorized ? props.authorized : props.notAuthorized}
</>
);
};
interface authorizedProps {
authorized: ReactElement;
notAuthorized?: ReactElement;
role?: string;
}
This component hides and shows diffrent kind of components depending on if the user is authorized or not.
I am using this component to only show the Login.tsx
component for users that are not logged in. I dont want anyone who is not logged in to be able to visit the website.
In my Index.tsx
I am using the Authorized.tsx
component like this
const Index = () => {
const [claims, setClaims] = useState<claim[]>([
// { name: "email", value: "test@hotmail.com" },
]);
return (
<div>
<BrowserRouter>
<AuthContext.Provider value={{ claims, update: setClaims }}>
<Authorized authorized={<App />} notAuthorized={<Login />} />
</AuthContext.Provider>
</BrowserRouter>
</div>
);
};
All the authorized users will be able to visit the site, everyone else will be asked to log in.
However, the problem I have is when I tried adding the Register.tsx
component into the Login.tsx
component as a navigational link.
I wish to be able to navigate between Register
and Login
This is how the Login.tsx
component looks like
export const Login = () => {
return (
<>
<h3>Log in</h3>
<DisplayErrors errors={errors} />
<AuthForm
model={{ email: "", password: "" }}
onSubmit={async (values) => await login(values)}
BtnText="Log in" />
<Switch>
<Route path="/register">
<Register />
</Route>
<Link to='/register'>Register</Link>
</Switch>
</>
);
};
But what actually happends when I press the 'Register' link is that the Register
component gets added below the Login
component
Before pressing the 'Register' link
After pressing the 'Register' link
I understand it has something to do with the Authorized.tsx
component in Index.tsx
.
That I am telling it to only show the Login component when not authorized.
But I dont know how I could fix it so I will be able to navigate between the Login
and the Register
All help I could get would be much appreciated!
Thanks
With the current implementation you are rendering a Login
component that then also renders a route for a Register
component to be rendered on. Login
remains mounted and rendered the entire time. From what you describe you want to render Login
and Register
each on their own route.
Abstract both these components into a parent component that manages the route matching and rendering.
Example
const Unauthenticated = () => (
<Switch>
<Route path="/register" component={Register} />
<Route component={Login} />
</Switch>
);
...
export const Login = () => {
...
return (
<>
<h3>Log in</h3>
<DisplayErrors errors={errors} />
<AuthForm
model={{ email: "", password: "" }}
onSubmit={login}
BtnText="Log in"
/>
<Link to='/register'>Register</Link>
</>
);
};
...
const Index = () => {
const [claims, setClaims] = useState<claim[]>([
// { name: "email", value: "test@hotmail.com" },
]);
return (
<div>
<BrowserRouter>
<AuthContext.Provider value={{ claims, update: setClaims }}>
<Authorized
authorized={<App />}
notAuthorized={<Unauthenticated />}
/>
</AuthContext.Provider>
</BrowserRouter>
</div>
);
};