Redirect doesn;t work, while {this.props.history} does - reactjs

While an action is successful, redirect is not working but history.replace is working.
Why??
import React, { Component } from "react";
import { Formik, Form, Field, ErrorMessage } from "formik";
import * as Yup from "yup";
import { withRouter } from "react-router-dom";
class Login extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div id="loginContainer" className="signinup-container">
<h3 className="mb-4"> Log In </h3>
<Formik
initialValues={{
email: "",
password: "",
rememberMe: false,
error: ""
}}
validationSchema={Yup.object().shape({
email: Yup.string()
.required("Please enter email to login.")
.email("Please enter a valid email."),
password: Yup.string().required("Please enter your password.")
})}
onSubmit={(values, { resetForm, setErrors, setSubmitting }) => {
setTimeout(() => {
console.log("Logging in", values);
setSubmitting(false);
return <Redirect to="/dashboard" />;
//this.props.history.replace("/dashboard");
//this.props.history.push('/dashboard');
}, 500);
}}
>
{props => {
const {
values,
touched,
errors,
isSubmitting,
handleChange
} = props;
return (
<Form id="loginForm" className="signinupForm" noValidate>
<ErrorMessage
name="error"
component="span"
className="login-error"
/>
<div className="form-group ">
<label className="form-label" htmlFor="email">
Email
</label>
<Field
type={"email"}
name="email"
placeholder="Enter your email"
className={
"form-control" +
(errors.email && touched.email ? " is-invalid" : "")
}
/>
<ErrorMessage
name="email"
component="span"
className="invalid-input"
/>
</div>
{/* Email */}
<div className="form-group position-relative">
<label className="form-label" htmlFor="password">
Password
</label>
<Field
type={"password"}
name="password"
placeholder="Enter your password"
className={
"form-control" +
(errors.password && touched.password ? " is-invalid" : "")
}
/>
<ErrorMessage
name="password"
component="span"
className="invalid-input"
/>
</div>
{/* Password */}
<div className="form-group">
<label className="form-label" htmlFor="rememberMe">
<input
type="checkbox"
id="rememberMe"
name="rememberMe"
onChange={handleChange}
defaultChecked={values.rememberMe}
value={values.rememberMe}
/>
Remember me
</label>
</div>
{/* Rememeber Me */}
{isSubmitting ? (
<span className="loader-gif">loading</span>
) : null}
<button
type="submit"
className="btn btn-filled"
disabled={isSubmitting}
>
Login
</button>
{/*Submit */}
</Form>
);
}}
</Formik>
</div>
);
}
}
export default withRouter(Login);
Please go to login page and check this.
Codesandbox link - https://codesandbox.io/s/winter-hooks-s9vgx

You are calling your Redirect JSX component from onSubmit method. However you cannot do that since you need to return the JSX elements from within the render method which is why you need to use history to update route
onSubmit={(values, { resetForm, setErrors, setSubmitting }) => {
setTimeout(() => {
console.log("Logging in", values);
setSubmitting(false);
this.props.history.replace("/dashboard");
}, 500);

You must be using slash:
to='/dashboard'

As what #Shubham Khatri said, but if you want to use <Redirect> you can create a state and detect if logged and then redirect it, like this.
Changes are adding
this.state = {
isLoggedIn: false
};
And in render
if (this.state.isLoggedIn) return <Redirect to="/dashboard" />;
in onSubmit
this.setState({ isLoggedIn: true });

Related

Redirect after logging in not Working Properly

Please i'm trying to redirect a user after logging in and it seems I'm doing something wrong because after logging in it doesn't redirect to the next page until i manually refresh the page
Here is the Signin component:
class Signin extends Component {
state = {
email: "",
password: "",
};
componentDidUpdate(){
console.log(this.props.isAuthenticated)
if(this.props.isAuthenticated) return <Redirect to= '/'/>
}
user = JSON.parse(localStorage.getItem("user"));
onChange = (e) => {
this.setState({
[e.target.id]: e.target.value,
});
};
onSubmit = (e) => {
e.preventDefault();
this.props.login(this.state);
};
render() {
if(this.user) return <Redirect to ='/'/>
return (
<Grid textAlign="center" verticalAlign="middle" className="app">
<Grid.Column style={{ maxWidth: 600 }}>
<Header as="h2" icon textAlign="center">
<Icon name="code branch" className="headerColor" />
<div className="headerColor">Login to ProGela</div>
</Header>
<Form size="large" onSubmit={this.onSubmit} className="form">
<Segment stacked>
<Form.Input
fluid
id="email"
icon="user"
iconPosition="left"
placeholder="Email"
onChange={this.onChange}
required
type="email"
/>
<Form.Input
fluid
id="password"
icon="lock"
iconPosition="left"
placeholder="Password"
onChange={this.onChange}
required
type="password"
/>
<Button color="red" className="headerColor" fluid size="large">
Sumit
</Button>
</Segment>
</Form>
</Grid.Column>
</Grid>
);
}
}
const mapStateToProps = (state) => {
return{
isAuthenticated: state.auth.isAuthenticated
}
}
export default connect(mapStateToProps, { login })(Signin);
i tried so many things, like i checked for the user if is present in the localstorage then let it redirect, check if user isAuthenicated from props, used that with componentDidUpdate Hooks still no progress

formik rendering an element when input field is clicked in react?

I am trying to make a simple login form i want to render an element when an input field is clicked . I have done this in normal react form by rendering an element by changing the value of a boolean variable to true and when the input is written if the user touch somewhere else then the element disapears . kind of toggle thing . but i don't know hoe to do this in formik. my code looks like this.
import React from "react";
import { Formik } from "formik";
import * as EmailValidator from "email-validator";
import * as Yup from "yup";
const ValidatedLoginForm = () => (
<Formik
initialValues={{ email: "", password: "" }}
onSubmit={(values, { setSubmitting }) => {
console.log(values);
console.log("hello there ");
}}
validationSchema={Yup.object().shape({
email: Yup.string()
.email()
.required("Required"),
password: Yup.string()
.required("No password provided.")
.min(8, "Password is too short - should be 8 chars minimum.")
.matches(/(?=.*[0-9])/, "Password must contain a number.")
})}>
{props => {
const {
values,
touched,
errors,
isSubmitting,
handleChange,
handleBlur,
handleSubmit
} = props;
return (
<div className="container">
<div className="row">
<form onSubmit={handleSubmit}>
<br />
<input
name="email"
type="text"
placeholder="Enter your email"
value={values.email}
onChange={handleChange}
onBlur={handleBlur}
className={errors.email && touched.email && "error"}
/>
<br />
<br />
{errors.email && touched.email && (
<div className="input-feedback">{errors.email}</div>
)}
<br />
<input
name="password"
type="password"
placeholder="Enter your password"
value={values.password}
onChange={handleChange}
onBlur={handleBlur}
className={errors.password && touched.password && "error"}
/> <br />
<br />
{errors.password && touched.password && (
<div className="input-feedback">{errors.password}</div>
)}
<button type="submit" disabled={isSubmitting}>
Login
</button>
</form>
</div>
<div className="row">
<button className="btn btn-default">Value</button>
</div>
</div>
);
}}
Maybe this will help you. Try to add function to onBlur prop then handle handleBlur function.
onBlur={(e) => {
handleBlur(e);
// here handle component showing
}}

How to disable button on submit form in formik?

I have a form in my react component with handleSubmit. What I need to do is when I submit the form(on save click) the save button automatically should get disabled and when I get the response it automatically gets enabled.
handleSubmit = async({ company, email }, { setSubmitting, setErrors }) => {
setSubmitting(true)
const { value: { status, message } } = await this.props.createCompany({ name: company, email })
if (status) {
this.fetchCompanies()
this.closeModal()
} else {
setErrors({ email: message })
}
}
<Formik
initialValues={loginDetails}
validationSchema={loginSchema}
onSubmit={(values, formikProps) => this.handleSubmit(values, formikProps)}
>
{({
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
isSubmitting
}) => (
<form onSubmit={handleSubmit}>
<div className="col-md-12">
<div className="form-group material-textfield">
<input type="text" name="email" value={values.email} onChange={handleChange} className="form-control material-textfield-input"/>
<ErrorMessage component="span" name="email" className="invalid-feedback d-block"/>
<label className="material-textfield-label">Email<span>*</span></label>
</div>
</div>
<button type="submit" className="btn btn-dark btn-lg w-100" disabled={isSubmitting}>Save</button>
</form>
)}
</Formik>
And for this I have used setSubmitting function from formik. But it doesn't work.
Kindly help.
This should help:
const onSubmitHandler = (values, formik) => {
persistYourData(values).then(r => {
formik.setSubmitting(false);
}).catch(error => console.log(error));
}
...
<Button variant="contained" color={"primary"} onClick={pr.handleSubmit} disabled={ ((!(pr.isValid && pr.dirty)) || pr.isSubmitting) }>Submit</Button>
#You can disable the button with **formik.isSubmitting** or **formik.errors** #
<Formik
initialValues={{
email: '',
password: '',
}}
validationSchema={Yup.object({
email: Yup.string().email('Invalid email address').required('Required'),
password: Yup.string().required('Required'),
})}
onSubmit={(values, { setSubmitting }) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
setSubmitting(false);
});
}}
>
{(formik) => (
<Form>
<h1>Login</h1>
<Field type='email' name='email' />
<br />
<ErrorMessage name='email' />
<br />
<Field type='password' name='password' />
<br />
<ErrorMessage name='password' />
<br />
<button disabled={formik.isSubmitting || formik.errors}>Login</button>
</Form>
)}
</Formik>

React, Display message after submitting form with react-hook-form

I use react-hook-form and would like to display message to the user after submitting form. I know how to do that with alert, but would like to have that message as a paragraph. After submitting fields should be again empty.
Here is my Form component:
import React from "react";
import { useForm } from "react-hook-form";
const Form = ({ title }) => {
const { register, handleSubmit, errors } = useForm();
const onSubmit = (data, e) => {
e.preventDefault();
console.log(data);
alert(`thank you ${data.name} for your message`);
};
return (
<div className="formContainer">
<Title title="Lets stay in touch" />
<div className="form">
<form onSubmit={handleSubmit(onSubmit)}>
<div className="form__row">
<input
className={`inputForm ${errors.name ? "inputFormError" : ""}`}
name="name"
type="text"
placeholder="name"
ref={register({ required: true })}
/>
<input
className={`inputForm ${
errors.surname ? "inputFormError" : ""
}`}
name="surname"
type="text"
placeholder="surname"
ref={register({ required: true })}
/>
</div>
<div>
<textarea
className={`inputForm areaForm ${
errors.message ? "inputFormError" : ""
}`}
name="message"
placeholder="Your message"
ref={register({ required: true })}
></textarea>
</div>
<div>
<button className="form__formButton" type="submit">
Send
</button>
</div>
</form>
</div>
</div>
);
};
export default Form;
Pretty simple with just a useState to show the message and reset API from hookForm to reset the form :
import React from "react";
import { useForm } from "react-hook-form";
const Form = ({ title }) => {
const [message, setMessage] = useState('');
const { register, handleSubmit, errors, reset } = useForm();
const onSubmit = (data, e) => {
e.preventDefault();
console.log(data);
setMessage(`thank you ${data.name} for your message`);
reset();
};
return (
<div className="formContainer">
<Title title="Lets stay in touch" />
<div className="form">
{message}
<form onSubmit={handleSubmit(onSubmit)}>
<div className="form__row">
<input
className={`inputForm ${errors.name ? "inputFormError" : ""}`}
name="name"
type="text"
placeholder="name"
ref={register({ required: true })}
/>
<input
className={`inputForm ${
errors.surname ? "inputFormError" : ""
}`}
name="surname"
type="text"
placeholder="surname"
ref={register({ required: true })}
/>
</div>
<div>
<textarea
className={`inputForm areaForm ${
errors.message ? "inputFormError" : ""
}`}
name="message"
placeholder="Your message"
ref={register({ required: true })}
></textarea>
</div>
<div>
<button className="form__formButton" type="submit">
Send
</button>
</div>
</form>
</div>
</div>
);
};
export default Form;

How to implement radio buttons in ReactJS with Formik

In my register form my radio buttons don't work, when I press the create button nothing happens, it doesn't activate the onSubmit function, but if I remove them it gets activated.
Here is my code:
import React from "react";
import { Formik, Field, Form, ErrorMessage } from "formik";
import * as Yup from "yup";
const male = props => (
<input type="radio" value="male" name="gender" {...props} />
);
const female = props => (
<input type="radio" value="female" name="gender" {...props} />
);
export class RegisterPage extends React.Component {
render() {
let { initialValues } = this.state;
return (
<div>
<div>
<h1>Sign Up</h1>
<Formik
initialValues={initialValues}
onSubmit={(
{ email, password, gender },
{ setStatus, setSubmitting }
) => {
setStatus();
authenticationservice.newuser({ email, password, gender }).then(
user => {
const { from } = this.props.location.state || { from: { pathname: "/" } `};`
this.props.history.push(from);
},
error => {
setSubmitting(false);
setStatus(error);
}
);
}}
render={({ errors, status, touched, isSubmitting }) => (
<Form>
<div>
<label htmlFor="email">Email Address</label>
<Field name="email" type="text" />
<ErrorMessage name="email" component="div" />
</div>
<div>
<label htmlFor="gender">Gender</label>
<label>Male</label>
<Field name="gender" as={male} />
<label>Female</label>
<Field name="gender" as={female} />
</div>
<div>
<button type="submit" disabled={isSubmitting}>
Create
</button>
{isSubmitting && <img alt="" src="data:image" />}
</div>
{status && <div>{status}</div>}
</Form>
)}
/>
</div>
</div>
);
}
}
I'm not sure what happens because I don't get any error codes, there is just not happening anything

Resources