how to hide and show input conditionally in React Js - reactjs

I Know this approach is not good in react js. but i don't know how to achieve same with react js. not getting the right way of doing this.
I have multiple input which I have to hide and show based on value selected from dropdown.
I am making this demo code for anyone who want to check.
https://codesandbox.io/s/gracious-hertz-k2ttl8?file=/src/App.js:0-1084
App.js
const App = () => {
const getInput = (e) => {
let input = e.target.value;
let data = document.getElementsByClassName(input);
data.array.forEach((ele) => {
if (ele.style.display === "none") {
ele.style.display = "block";
}
});
};
return (
<>
<select onChange={getInput}>
<option value="Address">Address</option>
<option value="Name">Name</option>
<option value="Both">Name && Address</option>
</select>
<br />
<br />
<input
className="Address Both"
type="text"
name="city"
placeholder="City"
/>
<input
className="Address Both"
type="text"
name="pincode"
placeholder="pincode"
/>
<br />
<br />
<input
className="Name Both"
type="text"
name="firstName"
placeholder="First Name"
/>
<input
className="Name Both"
type="text"
name="firstName"
placeholder="Last Name"
/>
</>
);
};
export default App;

You can use a state to store the selected value and then render the input based on that state:
const App = () => {
const [selected, setSelected] = useState("");
const getInput = (e) => {
setSelected(e.target.value);
};
return (
<>
<select onChange={getInput}>
<option value="Address">Address</option>
<option value="Name">Name</option>
<option value="Both">Name && Address</option>
</select>
<br />
<br />
{selected === 'Address'&&<input
className="Address Both"
type="text"
name="city"
placeholder="City"
/>}
// Similarly for the other inputs
</>
);
};

You can take a state that keeps track of the selected dropDown items.
const [selectedItem, setSelectedItem] = useState({
city: false,
pincode: false,
...
})
Then based on the state show the input put conditionally in the JSX something like the following codes:
{
selectedItem.city &&
<input
className="Address Both"
type="text"
name="city"
placeholder="City"
/>
}
You can follow the same thing for other input values also.
and don't forget to update selectedItem state on dropDown onChange function

i have made changes in your codesandbox , you need to use conditional rendering to show or hide component.

thank everyone who did answer to help me out
finally it working just as I want and I figure it out it was extra "br/" tag" which was the problem in the code
final code :
App.js
import { useState } from "react";
const App = () => {
const [display, setdisplay] = useState({
city: true,
pincode: true,
firstName: true,
lastName: true
});
const getInput = (e) => {
let input = e.target.value;
switch (input) {
case "Address": setdisplay({city: false, pincode: false, firstName: true, lastName: true }); break;
case "Name": setdisplay({ city: true, pincode: true, firstName: false, lastName: false }); break;
case "Both": setdisplay({city: false, pincode: false, firstName: false, lastName: false }); break;
default: setdisplay({});
}
};
return (
<>
<select onChange={getInput}>
<option value="Address">Address</option>
<option value="Name">Name</option>
<option value="Both">Both</option>
</select>
<br />
<input
style={{ display: display.city ? "none" : "inline-block" }}
className="Address Both"
type="text"
name="city"
placeholder="City"
/>
<input
style={{ display: display.pincode ? "none" : "inline-block" }}
className="Address Both"
type="text"
name="pincode"
placeholder="pincode"
/>
<input
style={{ display: display.firstName ? "none" : "inline-block" }}
className="Name Both"
type="text"
name="firstName"
placeholder="First Name"
/>
<input
style={{ display: display.lastName ? "none" : "inline-block" }}
className="Name Both"
type="text"
name="firstName"
placeholder="Last Name"
/>
</>
);
};
export default App;

Related

using useState to change get the input:text and using onclick to print new <p>

i'm a beginner in React and trying to learn useState. and I have difficulties on how to get the value of input and to save the value and print it on button click
const HomePage = () => {
const [state, setState] = useState({
Name: "",
surName: "",
});
const handleChange = (e) => {
setState({
...state,
[e.target.name]: e.target.value,
});
};
const RenderNameOC = () => {
return (
<p>
Halo {Name} {surName}
</p>
);
};
return (
<DivContainer>
<ContainerTitle>
<p>Exercise 2 - Form</p>
</ContainerTitle>
<InputContainer>
<InputArea>
<label>Name: </label>
<input type="text" value={state.Name} onChange={handleChange} />
</InputArea>
<InputArea>
<label>Surname: </label>
<input type="text" value={state.surName} onChange={handleChange} />
</InputArea>
<SubmitButton onClick={RenderNameOC}>Submit</SubmitButton>
</InputContainer>
</DivContainer>
);
};
export default HomePage;
this is my code right now and the error it gave me was 'name' and 'surname' is not defined.
my expected result is that there will be 2 input textbox with for name and surname. and when the button is clicked, it will add a new <p> below it.
Here should be state.Name and state.surName
<p>
Halo {state.Name} {state.surName}
</p>
And add name in both inputs
<input
type="text"
name="Name"
value={state.Name}
onChange={handleChange}
/>
<label>Surname: </label>
<input
type="text"
name="surName"
value={state.surName}
onChange={handleChange}
/>
But no point of returning anything RenderNameOC since onClick is a void function. Just move this template below the submit button
Demo

how to avoid repeating pattern when creating form in react

I am going to update the form with each keystroke with useState Hook this way I have to add an onChange event listener plus a function for each input and as you can imagine it's going to be lots of functions how can I avoid repeating myself?
function firstNamInput(){
}
function lastNameInput(){
}
function emailInput(){
}
function phoneInput(){
}
function addressInput(){
}
function genderInput(){
}
function jobInput(){
}
function ageInput(){
}
in react we try to collect form data on every keystroke but in the past, we used to collect form data when submit clicked. so because of this new approach, we have to listen for every keystroke on every input! isn't this crazy? yes, kind of but there is a way to go around I am going to explain it to you :
first I am going to talk about Rules you have to know about inputs:
we are going to use a useState Hook and we pass an object to it which contain:
a property for every input that's single
a property for group inputs (for example if there is checkboxes for gender we create only one property for gender)
what attributes every input should have?
name (it's going to be equal to its property in the useState)
value or checked (as a rule of thumb if the inputs gets true or false its usually checked vice versa )
onChange event
so let's create useState I am going to have a total of 7 properties in the object:
const [formData, setFormData] = React.useState(
{
firstName: "",
lastName: "",
email: "",
comments: "",
isFriendly: true,
employment: "",
favColor: ""
}
)
we need to create a function for the onChange event i am going to make it as reusable as possible it's going to get form data from each input and update it in our Hook.
function handleChange(event) {
const {name, value, type, checked} = event.target
setFormData(prevFormData => {
return {
...prevFormData,
[name]: type === "checkbox" ? checked : value
}
})
}
now we are going to add inputs look at note 2 again and now you are ready
import React from "react"
export default function Form() {
const [formData, setFormData] = React.useState(
{
firstName: "",
lastName: "",
email: "",
comments: "",
isFriendly: true,
employment: "",
favColor: ""
}
)
function handleChange(event) {
const {name, value, type, checked} = event.target
setFormData(prevFormData => {
return {
...prevFormData,
[name]: type === "checkbox" ? checked : value
}
})
}
function handleSubmit(event) {
event.preventDefault()
// submitToApi(formData)
console.log(formData)
}
return (
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="First Name"
onChange={handleChange}
name="firstName"
value={formData.firstName}
/>
<input
type="text"
placeholder="Last Name"
onChange={handleChange}
name="lastName"
value={formData.lastName}
/>
<input
type="email"
placeholder="Email"
onChange={handleChange}
name="email"
value={formData.email}
/>
<textarea
value={formData.comments}
placeholder="Comments"
onChange={handleChange}
name="comments"
/>
<input
type="checkbox"
id="isFriendly"
checked={formData.isFriendly}
onChange={handleChange}
name="isFriendly"
/>
<label htmlFor="isFriendly">Are you friendly?</label>
<br />
<br />
<fieldset>
<legend>Current employment status</legend>
<input
type="radio"
id="unemployed"
name="employment"
value="unemployed"
checked={formData.employment === "unemployed"}
onChange={handleChange}
/>
<label htmlFor="unemployed">Unemployed</label>
<br />
<input
type="radio"
id="part-time"
name="employment"
value="part-time"
checked={formData.employment === "part-time"}
onChange={handleChange}
/>
<label htmlFor="part-time">Part-time</label>
<br />
<input
type="radio"
id="full-time"
name="employment"
value="full-time"
checked={formData.employment === "full-time"}
onChange={handleChange}
/>
<label htmlFor="full-time">Full-time</label>
<br />
</fieldset>
<br />
<label htmlFor="favColor">What is your favorite color?</label>
<br />
<select
id="favColor"
value={formData.favColor}
onChange={handleChange}
name="favColor"
>
<option value="red">Red</option>
<option value="orange">Orange</option>
<option value="yellow">Yellow</option>
<option value="green">Green</option>
<option value="blue">Blue</option>
<option value="indigo">Indigo</option>
<option value="violet">Violet</option>
</select>
<br />
<br />
<button>Submit</button>
</form>
)
}

I am trying to set react-select values instead of using state for each select element i am trying to get all those values inside an array

When I use HTML select it works but it does not work with react-select
Also, the react-select options are arrays that I imported that return an object
Example:
const Program = [
{
value: "MSC",
label: "MSC"
},
{
value: "MCA",
label: "MCA",
isdisabled: true // disable this option
},
{
value: "BSC",
label: "BSC"
},
{
value: "BCA",
label: "BCA",
isdisabled: true // disable this option
}
];
import Select from "react-select";
function Download() {
const requestSelected = e => {
e.preventDefault();
// Axios.post('http://localhost:5000/login', attend)
// .then(res => {
// alert(res.data.message)
// })
console.log(selectedValue);
};
// set value for default selection
const [selectedValue, setSelectedValue] = useState({
Program: "",
Class: "",
Division: "",
Course: "",
Datefrom: "",
Datetill: ""
});
const handleChange = e => {
const { name, value } = e.target;
setSelectedValue({
...selectedValue,
[name]: value
});
};
return (
<form className="D Download" method="POST">
<p>Download Form:</p>
<label className="D_programlabel">Select Program:</label>
<Select
name="Program"
options={Program}
onChange={handleChange}
value={selectedValue.Program}
/>
<label className="D_classlabel">Select Class:</label>
<Select
name="Class"
options={Class}
onChange={handleChange}
value={selectedValue.Class}
/>
<label className="D_divisionlabel">Select Division:</label>
<Select
name="Division"
options={Division}
onChange={handleChange}
value={selectedValue.class}
/>
<label className="D_courselabel">Select Course:</label>
<Select
name="Course"
options={MSCCourses}
onChange={handleChange}
value={selectedValue.Course}
/>
<ul className="date_time-container">
<li>
<label>From Date :</label>
<input
type="date"
name="Datefrom"
placeholder="Enter Date"
onChange={handleChange}
value={selectedValue.Datefrom}
/>
</li>
<li>
<label>Till Date :</label>
<input
type="date"
name="Datetill"
placeholder="Enter Time"
onChange={handleChange}
value={selectedValue.Datetill}
/>
</li>
</ul>
<br />
<ul className="browse_upload-container">
<li>
<label>File :</label>
<input type="file" className="upload" accept=".csv" required></input>
<button type="submit" id="submit-file" class="btn btn-primary">
Download File
</button>
</li>
<li>
<input type="submit" value="Submit" onClick={requestSelected} />
</li>
</ul>
</form>
);
}
export default Download;
onChange return an item of options, so you should add name when call handleChange:
const handleChange = (name, value) => {
setSelectedValue({
...selectedValue,
[name]: value
})
}
onChange={(value) => handleChange("Program", value)}

Return value from a checkbox being checked in a mixed field react form

Ideally I want to use a single handleChanges function to set state for every field in my form. Right now, I don't really know how to make it so the checkboxes return a specific value, either true or false, or maybe even a string of "yes" or "no" depending on if they are toggled. I don't know where to put the logic for it.
Here is a simplified example of my form:
const ComponentFunction = props => {
const [fields, setFields] = useState({
inputTypeText: "",
textArea: "",
selectDropdown: "",
checkbox: "",
});
const handleChanges = event => {
setField({ ...fields, [event.target.name]: event.target.value });
};
const submitForm = event => {
event.preventDefault();
props.postForm(fields);
};
return (
<>
<form onSubmit={submitForm}>
<label htmlFor="inputTypeText">Input Type Text</label>
<input
id="title"
type="text"
name="title"
onChange={handleChanges}
value={property.title}
/>
<label htmlFor="textArea">Text Area</label>
<textarea
id="textArea"
rows="4"
cols="50"
name="textArea"
value={property.textArea}
onChange={handleChanges}
/>
<label htmlFor="selectDropdown">Select Dropdown</label>
<select onChange={handleChanges} value={property.selectDropdown} name="selectDropdown" id="select">
<option value="">--Select One--</option>
<option value="Stuff">Stuff</option>
</select>
<label htmlFor="checkbox>Check Box</label>
<input
id="checkbox"
name="checkbox"
type="checkbox"
value={property.checkbox}
onChange={handleChanges}
/>
<button type="submit">Submit</button>
</form>
</>
}
I ended up solving this by adding an additional handler just for checkboxes. Not sure if this is totally kosher, but it's pretty clean and worked perfectly.
This is the handler:
const handleClick = event => {
setFields({ ...fields, [event.target.name]: (event.target.checked ? "Checked" : "Not Checked") });
};
This is the checkbox:
<label htmlFor="checkbox">Check Box</label>
<input
id="checkbox"
name="checkbox"
type="checkbox"
onClick={handleClick}
/>

How to add Radio Button in Formik Validations Reactjs?

I am using Formik for Validating my Registration form I want to add validate gender via radio button how can I do that. I am not able to add radio button.
This is what I have done:-
const SignupSchema = Yup.object().shape({
email: Yup.string()
.email('Invalid email')
.required('Required'),
password: Yup.string()
.min(4, 'Password Must be four characters long!')
.max(20, 'Too Long!')
.required('Required'),
});
class Register extends Component {
render() {
return (
<Formik
initialValues={{
email: '',
password:'',
gender:'',
}}
validationSchema={SignupSchema}
onSubmit={values => {
console.log(values);
}}
>
{({ errors, touched }) => (
<Form>
<Field style={customStyles.textfield} placeholder="Email" name="email" type="email" />
{errors.email && touched.email ? <div}>{errors.email}</div> : null}
<Field placeholder="Enter Password" name="password" type="password" />
{errors.password && touched.password ? <div >{errors.password}</div> : null}
<button type="submit">Submit</button>
</Form>
)}
</Formik>
</div>
)
}
}
change gender initialValues as male
<Field
name="gender"
render={({ field }) => (
<>
<div className="radio-item">
<input
{...field}
id="male"
value="male"
checked={field.value === 'male'}
name="type"
type="radio"
/>
<label htmlFor="male">Male</label>
</div>
<div className="radio-item">
<input
{...field}
id="female"
value="female"
name="type"
checked={field.value === 'female'}
type="radio"
/>
<label htmlFor="female">Female</label>
</div>
</>
)}
/>
This solution gives you the chance to have more than 2 options.
Let say you have a file called Main.js and you want to put a radio button input in it. First, provide a list of options for your radio button in the Main.js
const radioOptions = [
{ key: 'Option 1', value: 'value 1' },
{ key: 'Option 2', value: 'value 2' },
{ key: 'Option 3', value: 'value 3' }
];
Next, create a RadioButton.js file with below code
import React from 'react';
import { Field } from 'formik';
const RadioButton = (props) => {
const { label, name, options, ...rest } = props;
return (
<div>
<label htmlFor={name}>{label}</label>
<Field name={name} {...rest} >
{
({ field }) => {
return options.map(option => {
return (
<React.Fragment key={option.key}>
<input
type='radio'
id={option.id}
{...field}
value={option.value}
checked={field.value === option.value}
/>
<label htmlFor={option.id}>{option.key}</label>
</React.Fragment>
);
})
}
}
</Field>
</div>
);
};
export default RadioButton;
Then put the reusable RadioButton Component in the Main.js wherever you want the radio button input to render.
The result UI will be 3 radio buttons with values "value 1", "value 2" and "value 3".
You can check out this awesome youtube series to know more.
This can be done simply but using this code below. it worked for me:
You will need to import Formik from "formik"
<Formik
initialValues={{
email: '',
password:'',
gender:'',
}}
// validations
validationSchema={SignupSchema}
onSubmit={values => { console.log(values); }}
>
{(formik) => (
<Form onSubmit={formik.handleSubmit}>
//Your Other inputs........
<div className="custom-control">
<input
id="male"
type="radio"
value="male"
name='gender'
onChange={formik.handleChange}
defaultChecked={formik.values.gender=== "male"}
/>
<label
className="custom-control-label"
htmlFor="male"
>
Male
</label>
</div>
<div className="custom-control">
<input
id="female"
type="radio"
value="female"
name='gender'
onChange={formik.handleChange}
defaultChecked={formik.values.gender=== "female"}
/>
<label
className="custom-control-label"
htmlFor="female"
>
Female
</label>
</div>
//Your Other inputs......
<button type="submit">Submit</button>
</Form>
)}
</Formik>

Resources