Если вход выполнен успешно, токен возвращается и сохраняется в локальном хранилище. В этом случае я должен перенаправить на приватный маршрут / панель. Если авторизация не удалась, я смогу показать сообщение об ошибке от ShowError()
. Функция сообщения об ошибке работала должным образом до того, как я добавил перенаправление.
Это мой LoginPage.tsx
function LoginPage (){
const [state, setState] = useState({
email: '',
password: '',
});
const [submitted, setSubmitted] = useState(false);
function ShowError(){
if (!localStorage.getItem('token'))
{
console.log('Login Not Successful');
return (
<ThemeProvider theme={colortheme}>
<Typography color='primary'>
Login Unsuccessful
</Typography>
</ThemeProvider>)
}
}
function FormSubmitted(){
setSubmitted(true);
console.log('Form submitted');
}
function RedirectionToPanel(){
if(submitted && localStorage.getItem('token')){
return <Redirect to='/panel'/>
}
}
// useEffect(() => {
// if(localStorage.getItem('token')){
// return <Redirect to='/panel'/>
// }
// },[] );
function submitForm(LoginMutation: any) {
const { email, password } = state;
if(email && password){
LoginMutation({
variables: {
email: email,
password: password,
},
}).then(({ data }: any) => {
localStorage.setItem('token', data.loginEmail.accessToken);
})
.catch(console.log)
}
}
return (
<Mutation mutation={LoginMutation}>
{(LoginMutation: any) => (
<Container component="main" maxWidth="xs">
<CssBaseline />
<div style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center'
}}>
<Avatar>
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
Sign in
</Typography>
<Formik
initialValues={{ email: '', password: '' }}
onSubmit={(values, actions) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
actions.setSubmitting(false);
}, 1000);
}}
validationSchema={schema}
>
{props => {
const {
values: { email, password },
errors,
touched,
handleChange,
isValid,
setFieldTouched
} = props;
const change = (name: string, e: any) => {
e.persist();
handleChange(e);
setFieldTouched(name, true, false);
setState( prevState => ({ ...prevState, [name]: e.target.value }));
};
return (
<form style={{ width: '100%' }}
onSubmit={e => {e.preventDefault();
submitForm(LoginMutation);FormSubmitted();RedirectionToPanel()}}>
<TextField
variant="outlined"
margin="normal"
id="email"
fullWidth
name="email"
helperText={touched.email ? errors.email : ""}
error={touched.email && Boolean(errors.email)}
label="Email"
value={email}
onChange={change.bind(null, "email")}
/>
<TextField
variant="outlined"
margin="normal"
fullWidth
id="password"
name="password"
helperText={touched.password ? errors.password : ""}
error={touched.password && Boolean(errors.password)}
label="Password"
type="password"
value={password}
onChange={change.bind(null, "password")}
/>
{submitted && ShowError()}
<FormControlLabel
control={<Checkbox value="remember" color="primary" />}
label="Remember me"
/>
<br />
<Button className='button-center'
type="submit"
disabled={!isValid || !email || !password}
// onClick={handleOpen}
style={{
background: '#6c74cc',
borderRadius: 3,
border: 0,
color: 'white',
height: 48,
padding: '0 30px'
}}
>
Submit</Button>
<br></br>
<Grid container>
<Grid item xs>
<Link href="#" variant="body2">
Forgot password?
</Link>
</Grid>
<Grid item>
<Link href="#" variant="body2">
{"Don't have an account? Sign Up"}
</Link>
</Grid>
</Grid>
</form>
)
}}
</Formik>
</div>
{submitted && <Redirect to='/panel'/>}
</Container>
)
}
</Mutation>
);
}
export default LoginPage;
В настоящее время, если вход не выполнен, он автоматически перенаправляется на страницу / 404. Однако я хочу, чтобы он направлял на / 404, только если введена недействительная / закрытая ссылка. В случае неудачного входа в систему я хочу показать сообщение об ошибке.
Я также попытался использовать UseEffect()
, что закомментировано в приведенном выше коде, но оно продолжает давать мне эту ошибку на стрелке:
Argument of type '() => JSX.Element | undefined' is not assignable to parameter of type 'EffectCallback'.
Type 'Element | undefined' is not assignable to type 'void | (() => void | undefined)'.
Type 'Element' is not assignable to type 'void | (() => void | undefined)'.
Type 'Element' is not assignable to type '() => void | undefined'.
Type 'Element' provides no match for the signature '(): void | undefined'.ts(2345)
вот как моя личная маршрутизация реализована в App.tsx
const token = localStorage.getItem('token');
const PrivateRoute = ({component, isAuthenticated, ...rest}: any) => {
const routeComponent = (props: any) => (
isAuthenticated
? React.createElement(component, props)
: <Redirect to={{pathname: '/404'}}/>
);
return <Route {...rest} render={routeComponent}/>;
};
Если я закомментирую {submitted && <Redirect to='/panel'/>}
, я получаю сообщение об ошибке при неудачном входе, но тогда нет перенаправление даже при успешном входе в систему.
Отредактированный код:
function LoginPage (){
const [state, setState] = useState({
email: '',
password: '',
});
const [submitted, setSubmitted] = useState(false);
const [shouldRedirect, setShouldRedirect] = useState(false);
function ShowError(){
if (!localStorage.getItem('token'))
{
console.log('Login Not Successful');
return (
<ThemeProvider theme={colortheme}>
<Typography color='primary'>
Login Unsuccessful
</Typography>
</ThemeProvider>)
}
}
// function FormSubmitted(){
// setSubmitted(true);
// console.log('Form submitted');
// }
function RedirectionToPanel(){
console.log('check');
if(submitted && localStorage.getItem('token')){
console.log('Finall');
return <Redirect to='/panel'/>
}
}
useEffect(() => {
if(localStorage.getItem('token')){
setShouldRedirect(true);
}
},[] );
function submitForm(LoginMutation: any) {
setSubmitted(true);
const { email, password } = state;
if(email && password){
LoginMutation({
variables: {
email: email,
password: password,
},
}).then(({ data }: any) => {
localStorage.setItem('token', data.loginEmail.accessToken);
})
.catch(console.log)
}
}
return (
<Mutation mutation={LoginMutation}>
{(LoginMutation: any) => (
<Container component="main" maxWidth="xs">
<CssBaseline />
<div style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center'
}}>
<Avatar>
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
Sign in
</Typography>
<Formik
initialValues={{ email: '', password: '' }}
onSubmit={(values, actions) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
actions.setSubmitting(false);
}, 1000);
}}
validationSchema={schema}
>
{props => {
const {
values: { email, password },
errors,
touched,
handleChange,
isValid,
setFieldTouched
} = props;
const change = (name: string, e: any) => {
e.persist();
handleChange(e);
setFieldTouched(name, true, false);
setState( prevState => ({ ...prevState, [name]: e.target.value }));
};
return (
<form style={{ width: '100%' }}
onSubmit={e => {e.preventDefault();
submitForm(LoginMutation);RedirectionToPanel()}}>
<TextField
variant="outlined"
margin="normal"
id="email"
fullWidth
name="email"
helperText={touched.email ? errors.email : ""}
error={touched.email && Boolean(errors.email)}
label="Email"
value={email}
onChange={change.bind(null, "email")}
/>
<TextField
variant="outlined"
margin="normal"
fullWidth
id="password"
name="password"
helperText={touched.password ? errors.password : ""}
error={touched.password && Boolean(errors.password)}
label="Password"
type="password"
value={password}
onChange={change.bind(null, "password")}
/>
{submitted && ShowError()}
<FormControlLabel
control={<Checkbox value="remember" color="primary" />}
label="Remember me"
/>
<br />
<Button className='button-center'
type="submit"
disabled={!isValid || !email || !password}
// onClick={handleOpen}
style={{
background: '#6c74cc',
borderRadius: 3,
border: 0,
color: 'white',
height: 48,
padding: '0 30px'
}}
>
Submit</Button>
</form>
)
}}
</Formik>
</div>
{/* {submitted && <Redirect to='/panel'/>} */}
</Container>
)
}
</Mutation>
);
}
export default LoginPage;