【问题标题】:Redirection In Some Cases Only仅在某些情况下重定向
【发布时间】:2020-06-20 14:44:03
【问题描述】:

我已经实现了这样的私有路由。如果 localStorage 中存在令牌,则可以访问私有路由。如果没有,我们应该重定向到 /404 页面:

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}/>;
};

但我也在我的 LoginPage 中使用重定向。

如果登录失败,我希望显示来自ShowError() 的错误消息。而不是重定向。在我添加重定向之前,这可以正常工作。如果登录成功,我应该去/面板。但是,现在,如果登录不成功,我就去/404。而不是显示错误消息。我该如何解决这个问题?

登录屏幕:

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);
}

function RedirectionToPanel(){
  if(submitted && 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>
                    </form>
                  )
                }}
              </Formik>
            </div>
            {submitted && <Redirect to='/panel'/>}
          </Container>
          )
        }
      </Mutation>
    );
}

export default LoginPage;

编辑::

我也试过用这个:

  if(localStorage.getItem('token')){
    return <Redirect to='/panel'/>
  }
});

但它在箭头上给了我一个错误:

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)

【问题讨论】:

    标签: javascript reactjs typescript react-router react-router-v4


    【解决方案1】:

    删除容器末尾的这一行。

    {submitted && <Redirect to='/panel'/>}
    

    因为在那里没有意义。 另外,调整提交方法以正确执行功能。

    function submitForm(LoginMutation: any) {
       const { email, password } = state;
       return LoginMutation({
         variables: {
           email,
           password,
         },
       }).then(({ data }: any) => {
          localStorage.setItem('token', data.loginEmail.accessToken);
       }).catch(console.error);
    }
    

    从 submitForm 方法返回 promise,您可以执行以下操作。

    onSubmit={e => {
       e.preventDefault();
       submitForm(LoginMutation).then((res: any) => {
          RedirectionToPanel();
          FormSubmitted();
       });
    }}
    

    【讨论】:

    • 如果我删除该行,当令牌也存在时重定向不会发生
    • 它也不会被执行,因为当组件被挂载时submitted 的值总是假的。从方法RedirectionToPanelif 语句中删除submitted 然后通过useEffect 调用它(如果有令牌,它会指向panel)或将组件更改为React.Component 你有很多方法在那里,它变得合理使用。
    • 另外,我收到一条错误消息,说 Property 'then' does not exist on type 'void'.ts(2339)on .then
    • 你能举个例子说明我如何在这里使用 useEffect 吗?之前没机会用过
    • 我用我如何尝试使用 UseEffect() 更新了问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-28
    • 2014-01-17
    • 2015-05-02
    • 2016-11-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多