I can use form inputs without ref and jnChange? - javascript

I have simple form
import React, { Component } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
const mySubmitForm = event => {
event.preventDefault();
const form = event.target;
form.firstName.classList.add("red");
console.log("This is first name value", (form.firstName.className = "red"));
console.log("This is last name value", form.lastName);
console.log("This is email value", form.email);
console.log("This is password", form.password);
};
const App = (props) => {
return (
<div className="App">
<form onSubmit={mySubmitForm}>
<fieldset>
<legend>Форма регистрации</legend>
Your name:{" "}
<input
className={this.state.isChangeClass ? "red" : ""}
type="text"
name="firstName"
/>
Your last name: <input type="text" name="lastName" />
Your email: <input type="text" name="email" />
Your password: <input type="password" name="password" />
<input type="submit" value="Send" />
</fieldset>
</form>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Sometimes to me don't need controlled input forms, especially when i have a lot of fields, can i use this method for send my form without refs and state(onChange), it's normal practice for optimization my React application?

Yes you can. Its a completely valid syntax and you can use it as long as any change does not require a re-render. (Like if one field has a dependency and updates or blocks any action like display a error message when field value changes or on blur)

Related

this.props.history.push('/') IS NOT WORKING in CLASS Component

Please help me to resolve the issue of this.props.history.push('/') IS NOT WORKING in CLASS Component. As we do not have any scope of using history anymore. Unable to implement navigate.
Please do help. Same issue with props.location.state.contact.
**const { name, email } = props.location.state.contact;**
import React, { Component } from "react";
import "../assets/css/AddContact.css";
import { Navigate } from "react-router-dom";
import { v4 as uuid } from "uuid";
class AddContact extends Component {
state = {
id: uuid(),
name: "",
email: "",
};
add = (e) => {
e.preventDefault();
if (this.state.name === "" || this.state.email === "") {
alert("All fields are required!");
return;
}
this.props.addContactHandler(this.state);
this.setState({ name: "", email: "" });
this.props.history.push("/");
};
render() {
return (
<div className="contactForm">
<h2 className="contactForm__title">Add Contact</h2>
<div className="contactForm__form">
<form action="/" method="post" onSubmit={this.add}>
<div className="contactForm__nameField">
<label htmlFor="name">Name</label>
<br />
<input
type="text"
placeholder="Enter your name"
name="name"
id="name"
value={this.state.name}
onChange={(e) => this.setState({ name: e.target.value })}
/>
</div>
<div className="contactForm__emailField">
<label htmlFor="email">Email</label>
<br />
<input
type="email"
placeholder="Enter your email"
name="email"
id="email"
value={this.state.email}
onChange={(e) => this.setState({ email: e.target.value })}
/>
</div>
<button className="contactForm__button">Add</button>
</form>
</div>
</div>
);
}
}
export default AddContact;
I tried out from all of my references.
You need to use the withRouter Higher Order Component provided with the React Router library in order to get access to those props (history and location automatically).
So just import that, and change your export to
export default withRouter(AddContact);
[Note that this assumes you are using React Router v5 or before - there is no withRouter in v6 which is the latest version. But your use of a class component implies that you are using an earlier version - v6 only works well if you use function components, as withRouter has been replaced with Hooks.]

why did not worked validation in react component

problem image is here-->
https://postimg.cc/4mYB30C6
There are two problems
One: warning me the controlled component to uncontrol though I use handler event;
Second: js include function 1st time define 2nd-time type error.
I cannot find my problem I use two-time value and define it with let but they told im not to define 2nd why include showing me type error
import React,{useState} from 'react'
//component
export default function Form() {
const [allValues,setAll] = useState({
name:"",
email:"",
pass:"",
nameerr:"",
passerr:"",
emailerr:"",
});
//valide function
let valide= ()=>{
let nameerr;
let passerr;
let emailerr;
if(!allValues.name)
{
nameerr='your name invalid';
}
if(!allValues.email.includes('#'))
{
emailerr='your Email invalid';
}
if(!allValues.pass.match(1))
{
passerr='your pass invalid';
}
if(nameerr||emailerr||passerr)
{
let newValue={nameerr,emailerr,passerr};
setAll(newValue);
return false;
}
return true;
}
//Onchange handaler
const handalChange=(e)=>{
setAll({...allValues,[e.target.name]:e.target.value});
}
//Onsubmit handaler
const handalSubmit=(e)=>{
e.preventDefault();
const NewValide=valide();
if(NewValide!==false){
let value={...allValues,
nameerr:"",
passerr:"",
emailerr:"",}
setAll(value);
console.log(value)
}
else{
valide();
}
}
return (
<form onSubmit={handalSubmit} >
<div>
Name: <input
placeholder="name"
type="text"
name="name"
value={allValues.name}
onChange={handalChange}
/>
<div>{allValues.nameerr}</div>
<div>
Email: <input
placeholder="email"
type="text"
name="email"
onChange={handalChange}
value={allValues.email}
/>
</div>
<div>{allValues.emailerr}</div>
<div>
password: <input
placeholder="password"
type="password"
name="pass"
onChange={handalChange}
value={allValues.pass}
/>
</div>
<div>{allValues.passerr}</div>
</div>
<input type="submit" value="Submit"/>
</form >
)
}
You are using wrong syntax when you are calling setAll() in valide fuction.
Try to call
setAll({... allValues, nameerr:nameerr ,emailerr: emailerr,passerr: passerr})
By doing this you will have access to other properties of allValues

Next.js and react-hook-form - ref does not work [duplicate]

I'm trying to do validations for my form in react. I chose "react-hook-form" library. But I'm constantly getting error "Path.split is not a function. Even after using the default example given in their website, I'm getting the same error.
This is the default code given in the official site.
import React from "react";
import { useForm } from "react-hook-form";
export default function App() {
const { register, handleSubmit, watch, errors } = useForm();
const onSubmit = data => console.log(data);
console.log(watch("example")); // watch input value by passing the name of it
return (
{/* "handleSubmit" will validate your inputs before invoking "onSubmit" */}
<form onSubmit={handleSubmit(onSubmit)}>
{/* register your input into the hook by invoking the "register" function */}
<input name="example" defaultValue="test" ref={register} />
{/* include validation with required or other standard HTML validation rules */}
<input name="exampleRequired" ref={register({ required: true })} />
{/* errors will return when field validation fails */}
{errors.exampleRequired && <span>This field is required</span>}
<input type="submit" />
</form>
);
}
react-hook-form updated to 7.0.0 from 6.X.X and has breaking changes:
You have to replace all ref={register} with {...register('value_name')}
Example:
Version 6.X.X:
<input ref={register({ required: true })} name="test" />
Version 7.0.X:
<input {...register('test', { required: true })} />
Simple input with required and errors.message features, necessary changes in update:
From version 6.x.x:
function MyComponent(props) {
const { register, handleSubmit, errors } = useForm();
const onSubmit = (values) => {...};
return (
<div>
<form onSubmit={handleSubmit(onSubmit)}>
<input
name="message"
autoComplete="off"
ref={register({
required: "Required",
})}
/>
{errors.message && errors.message.message}
<input type="submit" />
</form>
</div>
);
}
To version 7.x.x:
function MyComponent(props) {
const { register, handleSubmit, formState: { errors }} = useForm();
const onSubmit = (values) => {...};
return (
<div>
<form onSubmit={handleSubmit(onSubmit)}>
<input
name="message"
autoComplete="off"
{...register("message", {
required: "Required",
})}
/>
{errors.message && errors.message.message}
<input type="submit" />
</form>
</div>
);
}
In addition to register fix, if you use errors from useForm(), now errors feature is exported from formState.
Worth mentioning that if you are using material ui or something similar, where ref={ref} throws an error (because it expects a different prop name instead of ref), you might want to
import { TextField } from '#material-ui/core';
return (
<TextField {...register('name')} />
)
there is a migration guide for this here, but still worth to mention
As noted above, there are changes to how register is to be used in v7
If you are still getting errors, ensure that id is actually a string and not any other type such as a number.
<input {...register(id)} />
import { useForm } from "react-hook-form";
export default function App() {
const { register, formState: { errors }, handleSubmit } = useForm();
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register("firstName", { required: true })} />
{errors.firstName?.type === 'required' && "First name is required"}
<input {...register("lastName", { required: true })} />
{errors.lastName && "Last name is required"}
<input type="submit" />
</form>
);
}

How to preserve initial state on change of input value in React?

I have the following code, simply want to update the text value on input field change.
import React, { useState } from 'react';
const Form = () => {
const initialState = {
name: 'John',
age: 25
};
const [{ name, age }, setFormState] = useState(initialState);
const handleNameChange = (e) => {
setFormState({
name: e.target.value
});
};
const handleAgeChange = (e) => {
setFormState({
age: e.target.value
})
};
return (
<>
<form onSubmit={(e) => e.preventDefault()}>
<label htmlFor='name'>Name: </label>
<input type='text' id='name' name='name' placeholder={name} onChange={handleNameChange} />
<p>The person's name is {name}.</p>
<br />
<label htmlFor='age'>Age: </label>
<input type='text' id='age' name='age' placeholder={age} onChange={handleAgeChange} />
<p>His/her age is {age}.</p>
</form>
</>
)
}
export default Form;
A working example here: https://codesandbox.io/s/react-playground-forked-tskj9?file=/Form.js
Problem is, when input a value in the name field, age field is cleared, vice versa. I understand that this might be due to the initialState is no longer valid after change in the field, but how can I preserve the values in one <input> and <p> while input in another?
While you could fix it by including the other property in setFormState, eg:
setFormState({
name: e.target.value
age,
});
Functional components are not class components - feel free to separate values out into separate variables if they're not related. This'll make the syntax a lot easier:
const Form = () => {
const [name, setName] = React.useState('John');
const [age, setAge] = React.useState(25);
const handleNameChange = (e) => {
setName(e.target.value);
};
const handleAgeChange = (e) => {
setAge(e.target.value);
};
return (
<form onSubmit={(e) => e.preventDefault()}>
<label htmlFor='name'>Name: </label>
<input type='text' id='name' name='name' placeholder={name} onChange={handleNameChange} />
<p>The person's name is {name}.</p>
<br />
<label htmlFor='age'>Age: </label>
<input type='text' id='age' name='age' placeholder={age} onChange={handleAgeChange} />
<p>His/her age is {age}.</p>
</form>
)
}
ReactDOM.render(<Form />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<div class="react"></div>
In useState hook the properties are not merged as it used to be in setState function within class components. You will have to include the missing fields, to keep them in the object.
setFormState({
name: e.target.value,
age,
});

multiple forms in one page - reactjs

I am building page where user can switch between login and signup mode by clicking the switch button.
Login form has 2 input fields and signup form has 3 input fields. My thinking was to build 2 separate forms independent from each other and use 2 separate custom hook instances.
import React, { useState } from "react";
import { useForm } from "../../shared/hooks/form-hook";
import Card from "../../shared/components/UIElements/Card";
import Input from "../../shared/components/FormElements/Input";
import Button from "../../shared/components/FormElements/Button";
import {
VALIDATOR_MINLENGTH,
VALIDATOR_EMAIL
} from "../../shared/util/validators";
import "./Auth.css";
const Auth = props => {
const [showLogin, setShowLogin] = useState(true);
const [formStateLogin, inputHandlerLogin] = useForm(
{
email: {
value: "",
isValid: false
},
password: {
value: "",
isValid: false
}
},
false
);
const [formStateSignup, inputHandlerSignup] = useForm(
{
name: {
value: "",
isValid: false
},
email: {
value: "",
isValid: false
},
password: {
value: "",
isValid: false
}
},
false
);
const loginSubmitHandler = event => {
event.preventDefault();
console.log("login handler");
};
const signupSubmitHandler = event => {
event.preventDefault();
console.log(formStateSignup.inputs);
};
const switchButtonHandler = () => {
setShowLogin(!showLogin);
};
return (
<Card className="authentication">
{showLogin ? (
<form onSubmit={loginSubmitHandler} className="place-form">
<h2>Enter your login details</h2>
<Input
id="email"
element="input"
type="email"
placeholder="Email address"
label="Email"
validators={[VALIDATOR_EMAIL(), VALIDATOR_MINLENGTH(5)]}
onInput={inputHandlerLogin}
errorText="Please enter valid email address"
/>
<Input
id="password"
element="input"
type="password"
placeholder="Password"
label="Password"
validators={[VALIDATOR_MINLENGTH(5)]}
onInput={inputHandlerLogin}
errorText="Please enter valid password (at least 5 chars)"
/>
<Button type="submit" disabled={!formStateLogin.isValid}>
LOGIN
</Button>
</form>
) : (
<form onSubmit={signupSubmitHandler} className="place-form">
<h2>Enter your signup details</h2>
<Input
id="name_s"
element="input"
type="text"
placeholder="Enter your name"
label="Name"
validators={[VALIDATOR_MINLENGTH(2)]}
onInput={inputHandlerSignup}
errorText="Please enter valid name at least 2 chars"
/>
<Input
id="email_s"
element="input"
type="email"
placeholder="Email address"
label="Email"
validators={[VALIDATOR_EMAIL(), VALIDATOR_MINLENGTH(5)]}
onInput={inputHandlerSignup}
errorText="Please enter valid email address"
/>
<Input
id="password_s"
element="input"
type="password"
placeholder="Password"
label="Password"
validators={[VALIDATOR_MINLENGTH(5)]}
onInput={inputHandlerSignup}
errorText="Please enter valid password (at least 5 chars)"
/>
<Button type="submit" disabled={!formStateSignup.isValid}>
LOGIN
</Button>
</form>
)}
<Button inverse onClick={switchButtonHandler}>
{showLogin ? "SWITCH TO SIGNUP" : "SWITCH TO LOGIN"}
</Button>
</Card>
);
};
export default Auth;
Both forms seem to render fine but the trouble is when I enter text in one form and decide to switch to other form, values from departed form are not lost but rather translated to new form:
Is this limitation of ReactJS, is it HTML? :) Or is it just my buggy code?
It's not a good convention to have two forms in one component, it makes a mess...I would make rather two separated components of LoginForm and SignUpForm and switch between them through ternary operator based on the state whatever way you like. Your forms and their state will be separated and code is more readable
It happens same for checkbox and radio buttons if you select radio button on first page then renders second page with radio button it will be automatically selected as dom operations are costly,
In your case react is just adding new third field and removing it you need to set the value attribute of fields to respective state.
you can actually. use the nested route to switch between components
import { Switch, Route } from 'react-router-dom';
<Switch>
<Route path='/register' >
// component 1
<Register />
</Route>
<Route path='/login' >
// component 2
<Login />
</Route>
</Switch>

Categories

Resources