Why is my useState not working (error in console)? - javascript

I have react components:
WelcomePage.jsx
import { useState } from "react";
import SignUpPage from "./SignUpPage";
function WelcomePage() {
const [signUp, toSignUp] = useState(false);
function signUpClick() {
toSignUp(true);
}
return (
<div>
{signUp ? (
<SignUpPage isOpen={toSignUp} back={toSignUp} />
) : (
<div className="Welcome_page__container animate__animated animate__fadeIn">
<h1 className="Welcome_page__title">Welcome to Hotel Review </h1>
<h3 className="Welcome_page__subtitle">Sign in :</h3>
<div className="Welcome_page__wrapper">
<label className="Welcome_page__input-title" htmlFor="welcome_mail">
E-mail:
</label>
<input
value={inputEmail}
onInput={(e) => setInputEmail(e.target.value)}
className="Welcome_page__input"
id="welcome_mail"
type="email"
placeholder="Your e-mail..."
/>
<label className="Welcome_page__input-title" htmlFor="welcome_pass">
Password:
</label>
<input
value={inputPass}
onInput={(e) => setInputPass(e.target.value)}
className="Welcome_page__input"
id="welcome_pass"
type="password"
placeholder="Your password..."
/>
<button className="Welcome_page__btn" onClick={loginClick}>
Login
</button>
<button className="Welcome_page__btn" onClick={signUpClick}>
Sign Up
</button>
</div>
</div>
)}
</div>
);
}
export default WelcomePage;
SignUpPage.jsx
import { useState } from "react";
import { Hotels } from "./Hotels";
function SignUpPage(props) {
const { isOpen, back } = props;
const [isSignUp, setSignUp] = useState(false);
return (
<div>
{isSignUp ? (
<Hotels />
) : (
<div className="Welcome_page__container animate__animated animate__fadeIn">
<button onClick={back(false)}>Back...</button>
<h1 className="Welcome_page__title">Welcome to Hotel Review </h1>
<h3 className="Welcome_page__subtitle">Sign up :</h3>
<div className="Welcome_page__wrapper">
<label className="Welcome_page__input-title" htmlFor="welcome_mail">
E-mail:
</label>
<input
value={inputEmail}
onInput={(e) => setInputEmail(e.target.value)}
className="Welcome_page__input"
id="welcome_mail"
type="email"
placeholder="Your e-mail..."
/>
<label className="Welcome_page__input-title" htmlFor="welcome_pass">
Password:
</label>
<input
value={inputPass}
onInput={(e) => setInputPass(e.target.value)}
className="Welcome_page__input"
id="welcome_pass"
type="password"
placeholder="Your password..."
/>
<label
className="Welcome_page__input-title"
htmlFor="welcome_pass"
></label>
<input
value={inputPass2}
onInput={(e) => setInputPass2(e.target.value)}
className="Welcome_page__input"
id="welcome_pass_repeat"
type="password"
placeholder="Repeat password..."
/>
<button className="Welcome_page__btn_2">Sign Up</button>
</div>
</div>
)}
</div>
);
}
export default SignUpPage;
When I click on Back in the SignUpPage component I get an error -
It is necessary that after clicking on back there is a return to WelcomePage.jsx
Maybe I'm not using or passing useState in SignUpPage.jsx
I read about the error on the Internet, they say that you need to useEffect (), but I doubt that this is the problem ...

Here is the error:
<button onClick={back(false)}>Back...</button>
You are basically calling the back function immediately causing the WelcomePage component to update while rendering the SignUpPage component.
You should do this:
<button onClick={() => back(false)}>Back...</button>
By doing this you are going to execute the back function only when you click on the button

Related

Issue with form submit using Reactjs

I am working on Reactjs(Nextjs),Trying to submit form but unable to submit form,How can i submit form data ? Here is my current code
export default function Home() {
const checklogin = async (e:any) => {
e.preventDefault();
alert("Its working");
}
<form className="forms-sample" onSubmit={checklogin}>
<div className="form-group first">
<label htmlFor="username">Username</label>
<input
type="text"
className="form-control"
placeholder="your-email#gmail.com"
id="username"
/>
</div>
<div className="form-group last mb-3">
<label htmlFor="password">Password</label>
<input
type="password"
className="form-control"
placeholder="Your Password"
id="password"
/>
</div>
<input
type="submit"
name="submit"
defaultValue="Log In"
className="btn btn-block btn-primary"
/>
</form>
1. controlled form
import React from 'react';
export default function Home() {
const INITIAL_DATA = {
username: '',
password: '',
};
const [formData, setFormData] = React.useState(INITIAL_DATA);
const checklogin = async (e) => {
e.preventDefault();
console.log(formData); // * PROCESS FORMDATA ON SUBMIT
alert('Its working');
setFormData(INITIAL_DATA); // * CLEAR DATA AFTER SUBMIT
};
function handleOnChangeInput(event) {
const name = event?.target?.name;
const value = event?.target?.value;
setFormData((prev) => ({
...prev,
[name]: value,
}));
}
return (
<form className='forms-sample' onSubmit={checklogin}>
<div className='form-group first'>
<label htmlFor='username'>Username</label>
<input
type='text'
className='form-control'
placeholder='your-email#gmail.com'
id='username'
onChange={handleOnChangeInput}
value={formData?.username}
/>
</div>
<div className='form-group last mb-3'>
<label htmlFor='password'>Password</label>
<input
type='password'
className='form-control'
placeholder='Your Password'
id='password'
onChange={handleOnChangeInput}
value={formData?.password}
/>
</div>
<input
type='submit'
name='submit'
defaultValue='Log In'
className='btn btn-block btn-primary'
/>
</form>
);
}
2. Uncontrolled form
import React from 'react';
export default function Home() {
const formRef = React.useRef(null);
const checklogin = async (event) => {
event.preventDefault();
alert('Its working');
// * Get form enteries
const formData = new FormData(formRef?.current);
const formEnteries = Object.fromEntries(formData?.entries());
console.log(formEnteries); // * PROCESS FORMENTERIES ON SUBMIT
// * Clear form fields here
const formCurrentTarget = event?.currentTarget;
formCurrentTarget?.reset();
};
return (
<form className='forms-sample' onSubmit={checklogin} ref={formRef}>
<div className='form-group first'>
<label htmlFor='username'>Username</label>
<input
type='text'
className='form-control'
placeholder='your-email#gmail.com'
id='username'
name='username'
/>
</div>
<div className='form-group last mb-3'>
<label htmlFor='password'>Password</label>
<input
type='password'
className='form-control'
placeholder='Your Password'
id='password'
name='password'
/>
</div>
<input
type='submit'
name='submit'
defaultValue='Log In'
className='btn btn-block btn-primary'
/>
</form>
);
}
Read more about controlled and uncontrolled components here - Link

setting the value of more than one input

I am trying to build a login form. I am trying to set up the value of the email & password field individually. But as soon as I try to enter the text in the email text field, the same appears in the password field too. Can I have a solution to this?
Below is the code.
I guess the error is in OnChange fn where I am assigning the same value e.target.value to both the {email, passwaord}.
import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
const LoginPage = () => {
let navigate = useNavigate();
const [credentials, setCredentials] = useState({email:"",password:""});
const onChange = (e) => {
setCredentials({email: e.target.value ,password: e.target.value})
console.log(credentials.email, credentials.password)
}
const goToSignUp = () => {
navigate("/signup");
}
return (
<>
<div className="container my-5">
<div id="loginbody">
<div className="mt-3">
<h2 className="my-3 display-3">Login Here</h2>
<form className="login-form p-5">
<div className="mb-3">
<label for="exampleInputEmail1" className="form-label">
Email address
</label>
<input
type="email"
className="form-control"
id="email"
name="email"
value={credentials.email}
aria-describedby="emailHelp"
onChange={onChange}
/>
<div id="emailHelp" className="form-text">
We'll never share your email with anyone else.
</div>
</div>
<div className="mb-3">
<label for="exampleInputPassword1" className="form-label">
Password
</label>
<input
type="password"
className="form-control"
id="password"
name="password"
value={credentials.password}
onChange={onChange}
/>
</div>
<div className="d-grid gap-2 my-4 col-6 mx-auto">
<button type="submit" className="btn btn-success">
Submit
</button>
</div>
<hr />
<div className="mb-3 text-center">
<div id="emailHelp" className="form-text center my-3">
Didn't have an account ?
</div>
<div className="d-grid gap-2 my-3 col-6 mx-auto">
<button onClick={goToSignUp} className="btn btn-success ">
SignUp Here !
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</>
);
};
export default LoginPage;
You have identified the problem. You need to pass the key to change as well.
Here passing a callback to setState which provides the current state as a parameter, cloning the state object using spread syntax, and then updating the relevant property in the copied object using the passed key as a computed property name.
const LoginPage = () => {
const [credentials, setCredentials] = useState({email:"",password:""});
const onChange = (e, key) => {
setCredentials(prevCredentials => ({...prevCredentials, [key]: e.target.value}))
}
return (
<>
//...
<input
type="email"
className="form-control"
id="email"
name="email"
value={credentials.email}
aria-describedby="emailHelp"
onChange={(e) => onChange(e, 'email')}
/>
//...
<input
type="password"
className="form-control"
id="password"
name="password"
value={credentials.password}
onChange={(e) => onChange(e, 'password')}
/>
//...
</>
);
};
Note: Calling console.log() right after setting state will not log the updated state, the new state values won't be available until the next render cycle. see: useState set method not reflecting change immediately
Use the proper key to the respective fields
const onChange = (e) => {
setCredentials({ ...credentials, [e.target.name]: e.target.value})
console.log(credentials);
}

handling events in react

I need to make a login page, when I click the submit button this should be navigated to Dashboard page. The below is my code, what is the problem in it. When I give details in the login page and click on login, the details vanishes and not navigated to dashboard.
import React, { Component, useState } from "react";
import axios from 'axios';
import { setUserSession } from '../utils/common';
function Login(props) {
const username = useFormInput('');
const password = useFormInput('');
const [error, setError] = useState(null);
const [loading, setLoading] = useState(false);
// handle button click of login form
const handleLogin = () => {
props.history.push('/dashboard');
}
return (
<form>
<h3>Sign In</h3>
<div className="form-group">
<label>Email address</label>
<input type="email" className="form-control" placeholder="Enter email" />
</div>
<div className="form-group">
<label>Password</label>
<input type="password" className="form-control" placeholder="Enter password" />
</div>
<div className="form-group">
<div className="custom-control custom-checkbox">
<input type="checkbox" className="custom-control-input" id="customCheck1" />
<label className="custom-control-label" htmlFor="customCheck1">Remember me</label>
</div>
</div>
{error && <><small style={{ color: 'red' }}>{error}</small><br /></>}<br />
<input type="button" className="btn btn-primary btn-block" value={loading ? 'Loading...' : 'Sign-in'} onClick={handleLogin} disabled={loading} /><br />
<p className="forgot-password text-right">
Forgot password?
</p>
</form>
);
}
const useFormInput = initialValue => {
const [value, setValue] = useState(initialValue);
const handleChange = e => {
setValue(e.target.value);
}
return {
value,
onChange: handleChange
}
}
export default Login;
Do you have a route defined for /dashboard. Everything worked me in code sandbox without react router setup. Psuedo code shown below
<Switch>
<Route path="/dashboard">
<DashboardComponent />
</Route>
</Switch>

Why css file of one component interacted with the css file of another component in ReactJS? How to handle it?

I am trying to make a website template with Reactjs. In the Jumbotron section i make subscription form and in the home section User Entry form. But the css of one component interacted with another's one. How can i handle it?
[1]: https://i.stack.imgur.com/Wd4OQ.png
User EntryJs:-
import React, { Component } from 'react'
import './User Entry.css'
class Form extends Component {
initialState = {
name: "",
age: "",
job: ""
}
state = this.initialState
changeHandler = event => {
const { name, value } = event.target
this.setState({
[name]: value
})
}
render() {
const { name, job, age } = this.state
return (
<form className="form-inline">
<div className="row">
<div className="col-md-3">
<div className="form-group">
<label htmlFor="name">Name:-</label>
<input type="text"
className="form-control"
name="name"
id="name"
value={name}
autoFocus
onChange={this.changeHandler} />
</div>
</div>
<div className="col-md-3">
<div className="form-group">
<label htmlFor="age">Age:-</label>
<input type="text"
className="form-control"
name="age"
id="age"
value={age}
autoFocus
onChange={this.changeHandler} />
</div>
</div>
<div className="col-md-3">
<div className="form-group">
<label htmlFor="job">Job:-</label>
<input type="text"
className="form-control"
name="job"
id="job"
value={job}
autoFocus
onChange={this.changeHandler} />
</div>
</div>
<div className="col-md-3"></div>
</div>
</form>
)
}
}
export default Form
Header JS:-
import React, { Component } from 'react'
import './Header.css'
import { Link, withRouter } from "react-router-dom";
class Header extends Component {
constructor(props) {
super(props)
this.state = {
email: ""
}
}
submitHandler = event => {
event.preventDefault();
alert(`Subscribed Email is : ${this.state.email}`);
}
changeHandler = event => {
this.setState({
email: event.target.value
})
}
render() {
return (
// Navbar Starts
<div>
<div className="row navbar">
<Link to="/" style={{textDecoration:'none'}}><div className="col-md-2 logo">ReactApp</div></Link>
<div className="col-md-6"></div>
<Link to="/" style={{textDecoration:'none'}}> <div className="col-md-1 link"> Home</div> </Link>
<Link to="/about" style={{textDecoration:'none'}}> <div className="col-md-1 link"> About</div> </Link>
<Link to="/counter" style={{textDecoration:'none'}}> <div className="col-md-1 link"> Counter </div></Link>
<Link style={{textDecoration:'none'}}><div className="col-md-1 link">Login</div></Link>
</div>
<div className="jumbotron text-center">
<h1>React-App</h1>
<p>We specialize in <strong>Web Development</strong></p>
{/* Subscribing form starts*/}
<form className="form-inline subscribingForm" onSubmit={this.submitHandler}>
<div className="input-group">
<input type="email"
className="form-control"
value={this.state.email}
onChange={this.changeHandler}
size="80"
placeholder="Email..."
required />
<div className="input-group-btn">
<input type="submit" value="Subscribe" className="subscribingBtn" />
</div>
</div>
</form>
{/* Subscribing form closes*/}
</div>
</div>
)
}
}
export default withRouter(Header);
Where is the .css file loaded, in the root component? It probably is loaded globally and is used on every component.Better use JSS (https://cssinjs.org/?v=v10.3.0)
In general react transpiles all the css and add it in to tag.
And as result you one file css conflicts with other.
If you want to avoid this, you can use modular css.
https://create-react-app.dev/docs/adding-a-css-modules-stylesheet/

Keep code DRY on create/edit form

I have a few inputs that are used in my form for both create and update. I decided to make them a component.
// used for CRU on the event record
import React from 'react';
class Form extends React.Component {
render() {
return (
<div className="slds-form">
<div className="slds-form-element">
<label className="slds-form-element__label">Assigned To</label>
<div className="slds-form-element__control">
<input ref={(input) => this.assigned = input} type="text" className="slds-input" disabled/>
</div>
</div>
<div className="slds-form-element">
<label className="slds-form-element__label">Related To</label>
<div className="slds-form-element__control">
<input ref={(input) => this.related = input} type="text" className="slds-input" disabled/>
</div>
</div>
<div className="slds-form-element">
<label className="slds-form-element__label">Location</label>
<div className="slds-form-element__control">
<input ref={(input) => this.location = input} type="text" className="slds-input" />
</div>
</div>
<div className="slds-form-element">
<label className="slds-form-element__label">Event Start</label>
<div className="slds-form-element__control">
<input ref={(input) => this.start = input} type="text" className="slds-input" />
</div>
</div>
<div className="slds-form-element">
<label className="slds-form-element__label">Event End</label>
<div className="slds-form-element__control">
<input ref={(input) => this.end = input} type="text" className="slds-input" />
</div>
</div>
<div className="slds-form-element">
<label className="slds-form-element__label">Contact</label>
<div className="slds-form-element__control">
<input ref={(input) => this.contact = input} type="text" className="slds-input" disabled/>
</div>
</div>
<button type="button" className="slds-button slds-button--neutral">Cancel</button>
<button type="submit" className="slds-button slds-button--brand">{this.props.buttonLabel}</button>
</div>
);
}
}
export default Form;
I then attempted to use this component in my <Create /> component.
// used for Create on the event record
import React from 'react';
import Form from './Form';
class Create extends React.Component {
createEvent(e) {
console.log("createEvent() has fired.");
e.preventDefault();
const event = {
assigned: this.assigned.value,
related: this.related.value,
location: this.location.value,
start: this.start.value,
end: this.end.value,
contact: this.contact.value
}
console.log(event);
}
render() {
return (
<form onSubmit={(e) => this.createEvent(e)}>
<Form buttonLabel="Create" />
</form>
);
}
}
export default Create;
When I try to hit the Create button on my <Create /> component I get an error
Uncaught TypeError: Cannot read property 'value' of undefined
at Create.createEvent (webpack:///./src/components/Event/Create.js?:42:32)
at onSubmit (webpack:///./src/components/Event/Create.js?:59:27)
at Object.ReactErrorUtils.invokeGuardedCallback (webpack:///./~/react/lib/ReactErrorUtils.js?:70:16)
at executeDispatch (webpack:///./~/react/lib/EventPluginUtils.js?:89:21)
at Object.executeDispatchesInOrder (webpack:///./~/react/lib/EventPluginUtils.js?:112:5)
at executeDispatchesAndRelease (webpack:///./~/react/lib/EventPluginHub.js?:44:22)
at executeDispatchesAndReleaseTopLevel (webpack:///./~/react/lib/EventPluginHub.js?:55:10)
at Array.forEach (native)
at forEachAccumulated (webpack:///./~/react/lib/forEachAccumulated.js?:25:9)
at Object.processEventQueue (webpack:///./~/react/lib/EventPluginHub.js?:231:7)
I then check the console and see the refs belong in my <Form /> component, and not my <Create /> component.
Is there a way to pass the refs from my child component, <Form />, to its parent, <Create />?
That's a lot of refs! Good news, you really don't need them, at all. As a very very general rule, you should only be using refs if you are interacting with an external library that doesn't "understand" React (d3, Greensock, TinyMCE, etc).
Tackling it in an uncontrolled way can be done like:
const User = (props) => (
<div>
<input name="foo" className="form-control" />
<input name="foo2" className="form-control" />
<button type="submit" className="btn btn-primary">{props.buttonLabel}</button>
</div>
);
class App extends React.Component {
constructor(props) {
super(props);
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
onChange(e) {
this.setState({
[e.target.name]: e.target.value,
});
}
onSubmit(e) {
e.preventDefault();
console.log(this.state);
}
render() {
return (
<div className="container">
<br />
<form onChange={this.onChange} onSubmit={this.onSubmit}>
<User buttonLabel="Create"/>
</form>
</div>
);
}
};
ReactDOM.render(<App />, document.getElementById('app'));
Codepen example:
http://codepen.io/cjke/pen/zNXxga?editors=0010

Categories

Resources