由于函数的执行顺序,重定向不起作用 [英] Redirection Not Working Because of Order of Executions of Functions

查看:32
本文介绍了由于函数的执行顺序,重定向不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个登录页面.如果登录成功并且本地存储中存在令牌,我想重定向到私人页面/面板.我正在调用表单的 onSubmit() 上的所有函数.

这是我的代码的样子:

function LoginPage(){const [状态,设置状态] = useState({电子邮件: '',密码: '',});const [submitted, setSubmitted] = useState(false);函数显示错误(){if (!localStorage.getItem('token')){console.log('登录失败');}}函数表单提交(){设置提交(真);console.log('表单提交');}函数重定向到面板(){console.log('ha');if(submitted && localStorage.getItem('token')){console.log('FInall');return <Redirect to='/panel'/>}}函数 submitForm(LoginMutation: any) {const { 电子邮件,密码 } = 状态;如果(电子邮件和密码){登录变异({变量:{电子邮件:电子邮件,密码:密码,},}).then(({ data }: any) => {localStorage.setItem('token', data.loginEmail.accessToken);}).catch(控制台.log)}}返回 (<突变突变={LoginMutation}>{提交&&<重定向到='/面板'/>}{(LoginMutation: any) =>(<容器组件="main" maxWidth="xs"><CssBaseline/><div 样式={{显示:'弹性',flexDirection: '列',alignItems: '中心'}}><头像><LockOutlinedIcon/></头像><排版组件="h1"变体="h5">登入</排版><福米克initialValues={{ 电子邮件:'',密码:'' }}onSubmit={(values, actions) =>{setTimeout(() => {警报(JSON.stringify(值,空,2));动作.setSubmitting(假);}, 1000);}}验证架构={架构}>{道具=>{常量{值:{电子邮件,密码},错误,感动,处理更改,已验证,setFieldTouched} = 道具;const change = (name: string, e: any) =>{e.persist();handleChange(e);setFieldTouched(name, true, false);setState( prevState => ({ ...prevState, [name]: e.target.value }));};返回 (<form style={{ width: '100%' }}onSubmit={e =>{e.preventDefault();submitForm(LoginMutation);FormSubmitted();RedirectionToPanel()}}><文本字段变体=概述"边距=正常"id="电子邮件"全屏宽度名称=电子邮件"helperText={touched.email ?错误.电子邮件:"}错误={touched.email &&布尔值(errors.email)}标签=电子邮件"值={电子邮件}onChange={change.bind(null, "email")}/><文本字段变体=概述"边距=正常"全屏宽度id="密码"名称=密码"helperText={touched.password ?错误密码:"}错误={touched.password &&布尔值(错误.密码)}标签=密码"类型=密码"值={密码}onChange={change.bind(null, "password")}/>{提交&&显示错误()}<表单控件标签control={<Checkbox value="remember" color="primary"/>}标签=记住我"/><br/><Button className='button-center'类型=提交"禁用={!isValid ||!email ||!密码}//onClick={handleOpen}风格={{背景:'#6c74cc',边界半径:3,边界:0,白颜色',身高:48,填充:'0 30px'}}>提交</表单>)}}</Formik>

</容器>)}</突变>);}导出默认登录页面;

当我点击提交按钮时,我会检查控制台以了解 RedirectionToPanel() 函数内部发生的情况.第一次,'Ha' 被打印出来,但是当我第二次点击它时,'Ha' &'终于'被打印.但是,重定向仍然没有发生.

如果我使用 {submitted &&<Redirect to='/panel'/>}在突变之后,我在突变时收到此错误:

这个 JSX 标签的 'children' 属性需要一个类型为 '(mutateFunction: MutationFunction, result: MutationResult) =>元素 |null',但提供了多个孩子.ts(2746)

如果我在返回之后和变异之前使用它,我会在 && 上遇到语法错误和}.

解决方案

发生这种情况是因为 submitFormFormSubmitted 都包含异步操作.这意味着在 RedirectionToPanel 之后一个接一个地调用它们并不能保证它们按该顺序执行.考虑使用 useEffect 钩子在设置令牌后进行重定向.

此外,页面没有重定向的原因是您没有将 Redirect 组件返回到 DOM 树中.你可以通过插入一个检查提交状态的条件语句来解决这个问题

//当localStorage.getItem('token')发生变化时,执行回调useEffect(() => {设置提交(真);}, [localStorage.getItem('token')])...返回 (...<form style={{ width: '100%' }}onSubmit={e =>{e.preventDefault();submitForm(LoginMutation);}}>...//这条线可以在返回的任何地方.即使最后也很好{提交&&<重定向到='/面板'/>}<容器/>);

如果你想在没有 useEffect 的情况下做到这一点,你可以在 submitForm 中使用 setSubmitted.但即便如此,您也必须有 {submitted && DOM 中的某处

 function submitForm(LoginMutation: any) {const { 电子邮件,密码 } = 状态;如果(电子邮件和密码){登录变异({变量:{电子邮件:电子邮件,密码:密码,},}).then(({ data }: any) => {localStorage.setItem('token', data.loginEmail.accessToken);设置提交(真);}).catch(控制台.log)}}返回 (...<form style={{ width: '100%' }}onSubmit={e =>{e.preventDefault();submitForm(LoginMutation);}}>...//这条线可以在返回的任何地方.即使最后也很好{提交&&<重定向到='/面板'/>}<容器/>);

I have a login page. If login is successful and token is present in local storage, I want to redirect to a private page /panel. I am calling all functions on the onSubmit() of my form.

Here's what my code looks like:

function LoginPage (){
  const [state, setState] = useState({
    email: '',
    password: '',
  }); 

 const [submitted, setSubmitted] = useState(false);

function ShowError(){
  if (!localStorage.getItem('token'))
  {
    console.log('Login Not Successful');
  }
}

function FormSubmitted(){
  setSubmitted(true);
  console.log('Form submitted');
}

function RedirectionToPanel(){
  console.log('ha');
  if(submitted && localStorage.getItem('token')){
    console.log('FInall');
    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}>
        {submitted && <Redirect to='/panel'/>}
        {(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>
                    </form>
                  )
                }}
              </Formik>
            </div>
          </Container>
          )
        }
      </Mutation>
    );
}

export default LoginPage;

When I hit the submit button, I check the console for what happens inside the RedirectionToPanel() function. The first time, 'Ha' is printed but when I click on it for the second time, both 'Ha' & 'Finally' are printed. However, the redirection still doesn't happen.

If I use {submitted && <Redirect to='/panel'/>}after Mutation, I get this error on mutation:

This JSX tag's 'children' prop expects a single child of type '(mutateFunction: MutationFunction<any, Record<string, any>>, result: MutationResult<any>) => Element | null', but multiple children were provided.ts(2746)

If I use it after the return and before mutation, I get syntax errors on && and }.

解决方案

This is happening because submitForm and FormSubmitted both contain asynchronous operations. This means that calling them one after another followed by RedirectionToPanel does not guarantee that they execute in that order. Consider using the useEffect hook to do the redirect once the token is set.

Also, the reason why the page is not redirecting is because you are not returning the Redirect component into the DOM tree. You can fix this by inserting it with a conditional statement that checks the submitted state

//when localStorage.getItem('token') changes, execute the callback
useEffect(() => {
    setSubmitted(true);
}, [localStorage.getItem('token')])

...

return (
...
    <form style={{ width: '100%' }} 
                    onSubmit={e => {e.preventDefault();
                    submitForm(LoginMutation);}}>
...
    //This line can be anywhere in the return. Even at the end is fine
        {submitted && <Redirect to='/panel'/>}
    <Container />
);

If you want to do this without useEffect, you can use setSubmitted within submitForm. But even then, you must have {submitted && <Redirect to='/panel'/>} somewhere in your DOM

  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);
      setSubmitted(true);
    })
    .catch(console.log)
    }
  }

return (
...
    <form style={{ width: '100%' }} 
                    onSubmit={e => {e.preventDefault();
                    submitForm(LoginMutation);}}>
...
    //This line can be anywhere in the return. Even at the end is fine
        {submitted && <Redirect to='/panel'/>}
    <Container />
);

这篇关于由于函数的执行顺序,重定向不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆