useDispatch stops render of the page - reactjs

I'm using React, redux with typescript to build a frontend page. In one of the page, I want to register a user. I utilized useDispatch() and the page stops rendering. If I comment out the useDispatch() line, the page will render normally.
I can't find anything online regarding this.
const Register: FC<any> = () => {
const [formData, setFormData] = useState({
name: '',
email: '',
password: '',
password2: '',
})
// If I comment out this line, the page will render normally
const dispatch = useDispatch<any>()
const { name, email, password, password2 } = formData
const onSubmit = (e: any) => {
e.preventDefault()
if (password !== password2) {
toast.error('Passwords do not match')
} else {
const userData = {
name,
email,
password,
}
dispatch(register(userData))
}
}
const onChange = (e: any) => {
setFormData((prevState) => ({
...prevState,
[e.target.name]: e.target.value,
}))
}
return (
<>
<section className='heading'>
<h1>
<SlUserFollowing /> Register
</h1>
<p>Please create an account</p >
</section>
<section className='form'>
<form onSubmit={onSubmit}>
<div className='form-group'>
<input
type='text'
className='form-control'
id='name'
name='name'
value={name}
onChange={onChange}
placeholder='Enter your name'
required
/>
</div>
<div className='form-group'>
<input
type='email'
className='form-control'
id='email'
name='email'
value={email}
onChange={onChange}
placeholder='Enter your email'
required
/>
</div>
<div className='form-group'>
<input
type='password'
className='form-control'
id='password'
name='password'
value={password}
onChange={onChange}
placeholder='Enter password'
required
/>
</div>
<div className='form-group'>
<input
type='password'
className='form-control'
id='password2'
name='password2'
value={password2}
onChange={onChange}
placeholder='Confirm password'
required
/>
</div>
<div className='form-group'>
<button className='btn btn-block'>Submit</button>
</div>
</form>
</section>
</>
);
};
export default Register;
I searched online and didn't find any source regarding this.

Related

Fields tied to the state doesn't clear on successful form submission

I have a contact form, when the form submission is successful it should clear the form field name, email and message which is tied up to the state. The form submission is successful but form fields name, email and message doesn't clear.
For test purpose what I'm doing is passing default values to the state but this values doesn't get filled in form during initial load.
export default function Contact() {
const [name, setName] = useState('John Doe')
const [email, setEmail] = useState('me#example.com')
const [message, setMessage] = useState('Hello, this is test message.')
const onSubmit = (e) => {
e.preventDefault()
const form = {"name": name, "email": email, "message": message}
return fetch('/api/contact', {
method: 'POST',
body: JSON.stringify(form),
headers: {'Content-Type': 'application/json'}
}).then(response => {
if(response.status === 200){
setName('')
setEmail('')
setMessage('')
} else {
}
}).catch(err => err)
}
return (
<section>
<form method='post'>
<div>
<label>Name</label>
<input type="text" name="name" onChange={(e) => {setName(e.target.value)}}/>
</div>
<div>
<label>Email Address</label>
<input type="email" name="email" onChange={(e) => {setEmail(e.target.value)}}/>
</div>
<div>
<label>Message</label>
<textarea minLength={5} maxLength={2000} rows="6" name="message" onChange={(e) => {setMessage(e.target.value)}}></textarea>
</div>
<div>
<button type='submit' onClick={(e) => {onSubmit(e)}}>Send Message</button>
</div>
</form>
</section>
);
}
As User456 said, you need to add value={variable} for every <input />.
Example:
import { useState } from "react";
export default function Contact() {
const [name, setName] = useState("John Doe");
const [email, setEmail] = useState("me#example.com");
const [message, setMessage] = useState("Hello, this is test message.");
const onSubmit = (e: any) => {
e.preventDefault();
setName("");
setEmail("");
setMessage("");
};
return (
<section>
<form method="post">
<div>
<label>Name</label>
<input
type="text"
name="name"
value={name}
onChange={e => {
setName(e.target.value);
}}
/>
</div>
<div>
<label>Email Address</label>
<input
type="email"
name="email"
value={email}
onChange={e => {
setEmail(e.target.value);
}}
/>
</div>
<div>
<label>Message</label>
<textarea
minLength={5}
maxLength={2000}
name="message"
value={message}
onChange={e => {
setMessage(e.target.value);
}}></textarea>
</div>
<div>
<button
type="submit"
onClick={e => {
onSubmit(e);
}}>
Send Message
</button>
</div>
</form>
</section>
);
}

Can't input on other Form Fields

I'm using react. I was wondering on why can I only edit the FirstName part of the form while the other input fields wont let me type anything.
Here is my code:
import React, {useContext, useState, useEffect} from 'react';
import{GlobalContext} from '../context/GlobalState';
import {Link, useHistory} from 'react-router-dom';
import {Form,FormGroup,Label,Input,Button} from 'reactstrap';
export const EditUser = (props) => {
const {users,editEmployee } = useContext(GlobalContext);
const [selectedUser, setSelectedUser] = useState({
id:'',
name:'',
nameL:'',
email:'',
contact:'',
address:'',
date:'',
});
const history= useHistory();
const currentUserId = props.match.params.id;
useEffect(() =>{
const userId =(currentUserId);
const selectedUser =users.find(user=>user.id === userId)
setSelectedUser(selectedUser)
}, [currentUserId,users])
const onChange = (e) =>{
setSelectedUser({...selectedUser, [e.target.name]: e.target.value})
}
const onNameL = (e) =>{
setSelectedUser({...selectedUser, [e.target.nameL]: e.target.value})
}
const onEmail = (e) =>{
setSelectedUser({...selectedUser, [e.target.email]: e.target.value})
}
const onContact = (e) =>{
setSelectedUser({...selectedUser, [e.target.contact]: e.target.value})
}
const onAddress = (e) =>{
setSelectedUser({...selectedUser, [e.target.address]: e.target.value})
}
const onDate = (e) =>{
setSelectedUser({...selectedUser, [e.target.date]: e.target.value})
}
const onSubmit= () =>{
editEmployee(selectedUser)
history.push('/');
}
return (
<React.Fragment>
<Form onSubmit={onSubmit}>
<FormGroup>
<Label>FirstName</Label>
<Input type="text" name="name" value={selectedUser.name} onChange={onChange} placeholder="enter first name"></Input>
<Label>Last Name:</Label>
<Input type="text" name="nameL" value= {selectedUser.nameL} onChange={onNameL} placeholder="enter your Last name"></Input>
<Label>Email:</Label>
<Input type="email" name="email" value= {selectedUser.email} onChange={onEmail} placeholder="Email Address"></Input>
<Label>Contact Number:</Label>
<Input type="number" name="contact" value= {selectedUser.contact} onChange={onContact} placeholder="Contact"></Input>
<Label>Address:</Label>
<Input type="text"name="address" value= {selectedUser.address} onChange={onAddress} placeholder="enter your Address"></Input>
<Label>Date</Label>
<Input type="date" name="date" value= {selectedUser.date} onChange={onDate} placeholder="enter date employed"></Input>
</FormGroup>
<Button type="submit" className="btn btn-info">Edit </Button>
<Link to="/" className="btn btn-danger">Cancel</Link>
</Form>
</React.Fragment>
)
}
export default EditUser;
In all the functions which are being used to control form fields, use the following code:
setSelectedUser({...selectedUser, [e.target.name]: e.target.value})
Also, you can just use a single function i.e. onChange, for the current implementation. There is no use in using multiple functions.
Welcome to the Stack Overflow Community !!!
You can do that using fewer lines of code in a very optimized manner like this. It will fix your error & make it easier to debug. Try this out.
// necessary imports
export const EditUser = (props) => {
const [selectedUser, setSelectedUser] = useState({
id: "",
name: "",
nameL: "",
email: "",
contact: "",
address: "",
date: "",
});
const onChange = (e) => {
const property = e.target.name;
const value = e.target.value;
setSelectedUser({
...selectedUser,
[property]: value,
});
}; // Just have only one event for all form elements.
return (
<React.Fragment>
<Form>
<FormGroup>
<Label>FirstName</Label>
<Input
type="text"
name="name"
value={selectedUser.name}
onChange={onChange}
placeholder="enter first name"
></Input>
<Label>Last Name:</Label>
<Input
type="text"
name="nameL"
value={selectedUser.nameL}
onChange={onChange}
placeholder="enter your Last name"
></Input>
<Label>Email:</Label>
<Input
type="email"
name="email"
value={selectedUser.email}
onChange={onChange}
placeholder="Email Address"
></Input>
<Label>Contact Number:</Label>
<Input
type="number"
name="contact"
value={selectedUser.contact}
onChange={onChange}
placeholder="Contact"
></Input>
<Label>Address:</Label>
<Input
type="text"
name="address"
value={selectedUser.address}
onChange={onChange}
placeholder="enter your Address"
></Input>
<Label>Date</Label>
<Input
type="date"
name="date"
value={selectedUser.date}
onChange={onChange}
placeholder="enter date employed"
></Input>
</FormGroup>
<Button type="submit" className="btn btn-info">
Edit{" "}
</Button>
</Form>
</React.Fragment>
);
}
Let me know if you need further support.

React form with useState for multiple values

I have a demo here
It's a simple react form with typescript
Is it possible to use useState to capture the input fields data when the fields are completed
The form isn't just one piece of data but 3 - username, password and email
I could do it for one value with
onChange={e => setContact(e.target.value)}
but can I do it for 3 separate values
You can do it using computed properties.
First add a name property to each of your input, with values "username", "password", "email", then:
onChange={e => setContact(contact => ({...contact, [e.target.name]: e.target.value}))}
Edit: in React versions before 17, events are pooled and setContact update function is running asynchronously, so the event needs to be persisted this way:
onChange={e => {
e.persist();
setContact(contact => ({...contact, [e.target.name]: e.target.value}));
}}
Your handler could refer to the input name which you could then use to update the form object. There's a couple of issues with your syntax for this on the stackblitz - i.e the state object should be an object, not an array, so here's a full example:
const App = () => {
interface IForm {
username: string;
password: string;
email: string;
}
const [form, setFormValue] = useState<IForm>({
username: "",
password: "",
email: ""
});
const updateForm = (
formKey: keyof IForm,
event: React.ChangeEvent<HTMLInputElement>
) => {
const { value } = event.target;
setFormValue({
...form,
[formKey]: value
});
};
const handelSubmit = () => {
console.log("Form Submitted! Values: ", form);
};
return (
<div>
<form onSubmit={handelSubmit}>
<div>
<input
type="text"
placeholder="username"
value={form.username}
onChange={e => updateForm("username", e)}
/>
</div>
<div>
<input
type="password"
placeholder="password"
value={form.password}
onChange={e => updateForm("password", e)}
/>
</div>
<div>
<input
type="email"
placeholder="email"
value={form.email}
onChange={e => updateForm("email", e)}
/>
</div>
<input className="submit" type="submit" value="submit" />
</form>
</div>
);
};
You can create a object in the state and update the state with cloned object.
Here you go, Code with results as you expect:
import React, { useState } from "react";
import { render } from "react-dom";
import './style.css'
const App = () => {
interface IFrom {
username: string;
password: string;
email: string;
}
const [contact, setContact] = useState<IFrom[]>({
username:"",
email:"",
password:"",
});
console.log(contact)
const handelSubmit = () =>
{
axios.post(contact) //Example
};
return (
<div>
<form onSubmit={handelSubmit}>
<div>
<input
type="text"
placeholder="username"
value={contact.usename}
onChange={e => setContact({...contact, username: e.target.value})}
/>
</div>
<div>
<input
type="password"
placeholder="password"
onChange={e => setContact({...contact, password: e.target.value})}
/>
</div>
<div>
<input
type="email"
placeholder="email"
onChange={e => setContact({...contact, email: e.target.value})}
/>
</div>
<input className='submit' type="submi" value='submit'/>
</form>
</div>
);
};
render(<App />, document.getElementById("root"));

sweetalert pop up if passwords don't match

I want to make good pop up to my project with sweetalert when the passwords don't match:
const SignUp = ({ signUpStart, userError, resetError }) => {
const [userCredentials, setUserCredentials] = useState({
displayName: "",
email: "",
password: "",
confirmPassword: "",
});
const { displayName, email, password, confirmPassword } = userCredentials;
const handleSubmit = async (event) => {
event.preventDefault();
if (password !== confirmPassword) {
alert(`password don't match`);
return;
}
signUpStart({ displayName, email, password });
};
const handleChange = (event) => {
const { name, value } = event.target;
setUserCredentials({ ...userCredentials, [name]: value });
};
return (
<div className="signup">
<h2 className="title">I do not have a account</h2>
<span>Sign up with your email </span>
<form className="sign-up-form" onSubmit={handleSubmit}>
<Form
type="text"
name="displayName"
value={displayName}
onChange={handleChange}
label="Display Name"
required
></Form>
<Form
type="email"
name="email"
value={email}
onChange={handleChange}
label="Email"
required
></Form>
<Form
type="password"
name="password"
value={password}
onChange={handleChange}
label="Password"
required
></Form>
<Form
type="password"
name="confirmPassword"
value={confirmPassword}
onChange={handleChange}
label="Confirm Password"
required
></Form>
<CustomButton type="submit">SIGN UP</CustomButton>
</form>
{userError && userError.message ? (
<SweetAlert
show={!!userError.message}
type="warning"
title="Something went wrong"
text={userError.message}
onConfirm={() => resetError()}
/>
) : null}
</div>
);
};
EDIT: i add my whole component to the question. i deleted my mapstatetoprops and dispatch.
So i basically want to run once when i hit my submit button.
I want to make the alert in the if statement. But I think I need to refactor little. Can anyone help with this?

handleSubmit not getting called

I'm working on an app that uses strapi as the backenbd and react as the front
I'm using react hooks to build a login form. However my form submit does not call the submit handler
import React, { useState } from "react";
const Login = () => {
const [state, setState] = React.useState({ identifier: '', password: '' });
const handleChange = ({ target: { name, value } }) =>
setState(prevState => ({ ...prevState, [name]: value }));
const handleSubmit = async() => {
console.log('handleSubmit')
try {
const response = await fetch('./auth/local', { method: 'POST', body: state})
console.log(response)
} catch(err) {
console.log(err)
}
}
return (
<div>
<label htmlForm="identifier">identifier</label>
<input
id="identifier"
name="identifier"
onChange={handleChange}
value={state.identifier}
/>
<label htmlForm="password">password</label>
<input
id="password"
name="password"
onChange={handleChange}
value={state.password}
/>
<button onClick={() => handleSubmit}></button>
</div>
);
};
export default Login;
the handleSubmit function is never called.
You'd need to trigger the submit.
You can add a button to trigger a submit as shown below.
<div>
<form onSubmit={handleSubmit}>
<label htmlForm="identifier">identifier</label>
<input
id="identifier"
name="identifier"
onChange={handleChange}
value={state.identifier}
/>
<label htmlForm="password">password</label>
<input
id="password"
name="password"
onChange={handleChange}
value={state.password}
/>
👇
<button type="submit">Submit</button>
</form>
</div>
You can try it out out this Sandbox.
<div>
<label htmlForm="identifier">identifier</label>
<input
id="identifier"
name="identifier"
onChange={handleChange}
value={state.identifier}
/>
<label htmlForm="password">password</label>
<input
id="password"
name="password"
onChange={handleChange}
value={state.password}
/>
<button onClick={handleSubmit}></button>
</div>

Resources