【问题标题】:Redirection with useEffect() Not Working?使用 useEffect() 重定向不起作用?
【发布时间】:2020-06-21 13:15:03
【问题描述】:

如果登录成功并且令牌存储在 localStorage 中,我应该被重定向到私有路由,即 /panel。如果没有,我应该显示来自 ShowError() 的错误消息。

目前,如果登录不成功,则会显示我的错误消息,所以一切都很好。但是,如果存在令牌,则仍然没有重定向。

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);}}>
                      <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>
            <Box mt={8}>
              <Copyright />
            </Box>
            {/* {submitted && <Redirect to='/panel'/>} */}
          </Container>
          )
        }
      </Mutation>
    );
}

export default LoginPage;

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

export default function App() {
  return (
    <div>
      <BrowserRouter>
      <Switch>
      <Route exact path='/' component= {HomePage}></Route>
      <Route path='/login' component= {LoginPage}></Route>
      <Route path='/404' component= {Error404Page}></Route>
      <PrivateRoute
      path='/panel'
      isAuthenticated={token}
      component={PanelHomePage}
      />
      <Redirect from='*' to='/404' />
      </Switch>
      </BrowserRouter>
    </div>
  );
}

【问题讨论】:

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


    【解决方案1】:

    为什么要使用 useState 来重定向?直接重定向就好了。如果您使用的是react-router,最好使用useHistory

    import { useHistory } from 'react-router-dom';
    
    const history = useHistory();
    useEffect(() => {
        if(localStorage.getItem('token')){
          history.push({
            pathname: '/',
          });
        }
    },[]);
    

    如果你仍然想使用 useState,你可以创建一个新的 useEffect NS 将该状态添加到你的依赖数组中。

    const history = useHistory();
    useEffect(() => {
        if(localStorage.getItem('token')){
          setShouldRedirect(true);
        }
    },[]);
    
    useEffect(() => {
      if(shouldRedirect){
        history.push({
          pathname: '/',
        });
      }
    },[shouldRedirect]);
    

    【讨论】:

    • 我尝试使用您建议的第一种方法,但我的页面崩溃了:Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: 1. You might have mismatching versions of React and the renderer (such as React DOM) 2. You might be breaking the Rules of Hooks 3. You might have more than one copy of React in the same app
    • 实际上,当我导入 useHistory 时,我的 Visual Studio 文件开始显示一个黄点,当我初始化历史记录时,我得到了上面提到的错误。所以一切都崩溃了
    • @a125 您需要在返回模板之前将钩子放入组件函数中。
    猜你喜欢
    • 2015-02-27
    • 2018-07-02
    • 1970-01-01
    • 1970-01-01
    • 2020-02-15
    • 2017-10-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多