简体   繁体   中英

Redirecting the url after login (react js)

I'm a react js beginner. I got stuck in this problem for many days. I don't know how to redirect to path /users when the login is successful (no validation errors). If anything not clear, please tell me. It's my first time to ask question on stackoverflow. Please help:(

//app.js

import React from "react"
import ValidationLog from "./ValidationLog"
import PostList from "./PostList"
import  {BrowserRouter as Router,Route,Switch,Redirect}  from "react-router-dom"

function App() {
  

  return (
    <Router>
      <div className="App">

        <Switch>
          <Route exact path="/" component={ValidationLog}></Route>
          <Route path="/users" component={PostList}></Route>
        </Switch>
          
      </div>
    </Router>
  )
  
}
export default App

//ValidationLog.js

import React from "react"
import {Formik} from "formik"
import * as Yup from "yup"
import  {BrowserRouter as Router,Route,Switch,Redirect}  from "react-router-dom"


const ValidationLog = () => (
    
    <Formik 
    
     initialValues = {{email: "", password: ""}}
     onSubmit = {(values,{ setSubmitting}) => {
         setTimeout(() => {
            <Redirect to="/users" /> 
            
         }, 500);
     }}
     
     validationSchema = {Yup.object().shape({
        email: Yup.string()
            .email()
            .required("Required"),
        password: Yup.string()
            .required("No password provided")
            .min(8,"Password has to be at least 8 characters.")
     })
            
    }
    >
        {props => {
            const {
                values,
                touched,
                errors,
                isSubmitting,
                handleChange,
                handleBlur,
                handleSubmit
            } = props

            
            
            
            return (
                    
                    <div>
                        

                        <form autoComplete = "off" onSubmit = {handleSubmit}>
                            <h2 style={{fontSize: 22}}>Login to view our user pool</h2>
                            <label htmlFor="email">Email:</label>
                            <input type="text" value={values.email} name="email" onChange={handleChange} onBlur={handleBlur} placeholder="Enter your email" className={errors.email && touched.email && "error"}/>
                            {errors.email && touched.email && (<div className="input-feedback">{errors.email}</div>)}
                            <label htmlFor="email">Password:</label>
                            <input type="password" value={values.password} name="password" onChange={handleChange} onBlur={handleBlur} placeholder="Enter your password" className={errors.password && touched.password && "error"}/>
                            {errors.password && touched.password && (<div className="input-feedback">{errors.password}</div>)}
                            <button type="submit" disabled={isSubmitting}>Login</button>
                            
                        </form>

                    </div>
            )
        }}
    </Formik>
)


export default ValidationLog

The following is what I tried. I tried to add a <Redirect to /users/> in ValidationLog.js

 onSubmit = {(values,{ setSubmitting}) => {
         setTimeout(() => {
            <Redirect to="/users" /> 
            
         }, 500);
     }}

I also tried to set a variable islogin in ValidationLog.js and import in app.js when there is no validation errors but islogin is always false in app.js.

//ValidationLog.js

export let islogin = false
onSubmit = {(values,{ setSubmitting}) => {
         setTimeout(() => {
            islogin = true
            console.log(`Logged in ${islogin}`)
         }, 500);
     }}

//app.js

import ValidationLog,{islogin} from "./ValidationLog"

<Route exact path="/">
  {islogin ? <Redirect to="/users" /> : null}
</Route>

<Redirect... /> is a JSX-Construct to create a component at this position. By itself this does not do anything in imperative code-paths like your onSubmit handler.

What you are looking for is an imperative function that you can call outside a React-Tree. Like from the useHistory hook from react-router.

import { useHistory } from "react-router-dom";

...

const history = useHistory();

...

  onSubmit={() => history.push("/home")}

More specifically for your example:

const ValidationLog = () => {
  const history = useHistory();
  return (
    
    <Formik 
    
     initialValues = {{email: "", password: ""}}
     onSubmit = {(values,{ setSubmitting}) => {
         setTimeout(() => {
            history.push(...)
            
         }, 500);
     }}
...

You can do it using withRouter

Import withRouter from react-router-dom and enclose your component with withRouter in the export.

You can then navigate using this.props.history.push("/newurl")

import React from "react"
import {Formik} from "formik"
import * as Yup from "yup"
// import withRouter
import  {BrowserRouter as Router,Route,Switch,Redirect,withRouter}  from "react-router-dom"


const ValidationLog = (props) => (

<Formik 

 initialValues = {{email: "", password: ""}}
 onSubmit = {(values,{ setSubmitting}) => {
     setTimeout(() => {
        // this redirects to /users, make sure you get the import withRouter (check the last export line)
        props.history.push("/users");
        
     }, 500);
 }}
 
 validationSchema = {Yup.object().shape({
    email: Yup.string()
        .email()
        .required("Required"),
    password: Yup.string()
        .required("No password provided")
        .min(8,"Password has to be at least 8 characters.")
 })
        
}
>
    {props => {
        const {
            values,
            touched,
            errors,
            isSubmitting,
            handleChange,
            handleBlur,
            handleSubmit
        } = props

        
        
        
        return (
                
                <div>
                    

                    <form autoComplete = "off" onSubmit = {handleSubmit}>
                        <h2 style={{fontSize: 22}}>Login to view our user pool</h2>
                        <label htmlFor="email">Email:</label>
                        <input type="text" value={values.email} name="email" onChange={handleChange} onBlur={handleBlur} placeholder="Enter your email" className={errors.email && touched.email && "error"}/>
                        {errors.email && touched.email && (<div className="input-feedback">{errors.email}</div>)}
                        <label htmlFor="email">Password:</label>
                        <input type="password" value={values.password} name="password" onChange={handleChange} onBlur={handleBlur} placeholder="Enter your password" className={errors.password && touched.password && "error"}/>
                        {errors.password && touched.password && (<div className="input-feedback">{errors.password}</div>)}
                        <button type="submit" disabled={isSubmitting}>Login</button>
                        
                    </form>

                </div>
        )
    }}
</Formik>
)

// changes
export default withRouter(ValidationLog)

<Redirect> component approach here:

Use a state variable in your component

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

On submitting, if conditions for redirect are met set this state variable to true

setSubmitted(true);

In your component JSX, place the <Redirect to="/users" /> conditionally depending on that state variable

return <Fragment>
{ submitted 
? <Redirect to="/users" />
: <MyComponent ...> }
</Fragment>

Note

If you prefer to avoid this ternary operator syntax for whaterver reason, you could solve this with variables in the component logic before the return. Might be cleaner depending on the complexity of the component.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM