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.