Field Form doesn't update selected value in option - reactjs

I've React Final Form in my project. I have a problem with updating the displayed option in select. The entire form works fine, but doesn't change the display value.
function App() {
const [selectValue, setSelectValue] = useState();
return (
<Form
onSubmit={onSubmit}
initialValues={{}}
render={({ handleSubmit, form, submitting, pristine, values }) => (
<form onSubmit={handleSubmit}>
<label>Dish type</label>
<Field
name="type"
component="select"
defaultValue={selectValue}
onChange={(e) => setSelectValue(e.target.value)}
required
>
<option value="" />
<option value="pizza">pizza</option>
<option value="soup">soup</option>
<option value="sandwich">sandwich</option>
</Field>
</div>
</form>
)}
/>
);
On live-server option does not change its value. Displayed value is the same as the first time I selected.

Try to use the regular html select.
<select value={selectValue}
onChange={(e) => setSelectValue(e.target.value)}
required
>
<option value="" />
<option value="pizza">pizza</option>
<option value="soup">soup</option>
<option value="sandwich">sandwich</option></select>

Related

How do i chain filter method for filtering an array?

I want to display an array, and filtered it by a search field and multiple dropdown, i have succesfully implemented the search field, but i don't know how to chain the dropdown to the filter function
In summary, I want to add another search parameter like a select or dropdown, how do i chain it with this filtered function?
const filtered = () => {
if (search) {
return data.filter((items) =>
items.name.toLowerCase().includes(search.toLowerCase())
);
}
return data;
};
<form>
<div className="form-grid">
<select
name="search"
value={drop}
className="form-control"
onChange={handleDrop}
>
<option value="">ALL</option>
<option value="new">RECENTLY ADDED</option>
<option>SOON</option>
</select>
<input
type="text"
className="form-control"
placeholder="Search 160+ Data Source Connectors"
onChange={handleSearch}
name="search"
value={search}
/>
<select
value={type}
onChange={handleType}
name="type"
className="form-control form-select-lg"
>
<option value="">ALL</option>
<option>APPLICATION</option>
<option>FILE</option>
<option>DATABASE</option>
<option>EVENT</option>
</select>
</div>
</form>

How to set the value of a checkbox inside a form in reactjs

I have a form that I shall use for filtering searches. Along with other fields, I have a checkbox.
This is how I am handling the submit
const [formData, setFormData] = useState({
name: "",
location: "",
schoolName: "",
class: 0,
board: 0,
homeTuition: false,
});
const changeFormData = (e) => {
setFormData({
...formData,
[e.target.name]: e.target.value,
});
};
const formDataSubmit = (e) => {
e.preventDefault();
console.log(formData);
setFormData({
name: "",
location: "",
schoolName: "",
class: 0,
board: 0,
homeTuition: false,
});
};
<form onSubmit={(e) => formDataSubmit(e)}>
<div className="word">
<input
type="text"
name="name"
id="name"
placeholder="teacher name"
value={formData.name}
onChange={(e) => changeFormData(e)}
/>
</div>
<div className="word">
<input
type="text"
name="location"
id="location"
placeholder="location / area name"
value={formData.location}
onChange={(e) => changeFormData(e)}
/>
</div>
<div className="word">
<input
type="text"
name="schoolName"
id="schoolName"
placeholder="Name of School"
value={formData.schoolName}
onChange={(e) => changeFormData(e)}
/>
</div>
<div className="select-menu">
<select
value={formData.class}
name="class"
id="class"
onChange={(e) => changeFormData(e)}
>
<option value="0" disabled hidden>
Select Class
</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
</select>
</div>
<div className="select-menu">
<select
value={formData.board}
name="board"
id="board"
onChange={(e) => changeFormData(e)}
>
<option value="0" disabled hidden>
Select Board
</option>
<option value="mbose">MBOSE</option>
<option value="cbse">CBSE</option>
<option value="icse">ICSE</option>
</select>
</div>
<div className="home-tutor">
<label htmlFor="homeTuition">
Home Tutor
<input
type="checkbox"
name="homeTuition"
id="homeTuition"
value={formData.homeTuition}
onChange={(e) => changeFormData(e)}
/>
<span></span>
</label>
</div>
<div className="submit-button">
<button type="submit">Apply Filter</button>
</div>
</form>
I want to set homeTuition as true if checked else false. But since I am new to react I do not understand where to write this logic.
I tried using a seperate useState for this that changes the bool value onClick but I understood that it immediately doesn't effect the target.value. So please help me how should I do it?.
If you want to use a single handler:
const changeFormData = (e) => {
const { name, type } = e.target;
setFormData({
...formData,
[name]: e.target[type === "checkbox" ? "checked" : "value"]
});
};
return (
<input
type="text"
name="schoolName"
id="schoolName"
placeholder="Name of School"
value={formData.schoolName}
onChange={(e) => changeFormData(e)}
/>
<input
type="checkbox"
name="homeTuition"
id="homeTuition"
checked={formData.homeTuition}
onChange={(e) => changeFormData(e)}
/>
);
Add addition function:
const changeCheckbox = (e) => {
setFormData({
...formData,
[e.target.name]: e.target.checked,
});
};
Change input tag for checkbox (use 'checked' instead 'value' and new function):
<input
type="checkbox"
name="homeTuition"
id="homeTuition"
checked={formData.homeTuition}
onChange={(e) => changeCheckbox(e)}
/>

Simple React form is not showing the default value (reactHooks)

I'm following the official React docs to build a simple form which, however, doesn't work as intended.
const [value, setValue] = useState("banana")
...
<form onSubmit={handleSubmit}>
<label>
Pick your favorite flavor:
<select value={value} onChange={handleChange}>
<option value="grapefruit">Grapefruit</option>
<option value="lime">Lime</option>
<option value="coconut">Coconut</option>
<option value="mango">Mango</option>
</select>
</label>
<input type="submit" value="Submit" />
</form>
As far as I understood, it has to display "banana" as the initial value, whereas it shows "grapefruit". Why is it so?
Here's the link to the docs: https://reactjs.org/docs/forms.html
In the "Forms" section there's an example from where I took the code. It, however, uses class-based components while I use reactHooks. Might it be the problem?
Many thanks!
It shows the first option because value isn't an attribute of <select>. If you want to select one, you need to add a selected attribute to one of the options.
For example:
<label>
Pick your favorite flavor:
<select onChange={handleChange}>
<option value="grapefruit">Grapefruit</option>
<option value="lime">Lime</option>
<option selected={true} value="coconut">Coconut</option>
<option value="mango">Mango</option>
</select>
</label>
<input type="submit" value="Submit" />
This is generally written as
const options = ["grapefruit", "lime", "coconut", "mango"];
const selectedValue = "lime";
<label>
Pick your favorite flavor:
<select onChange={handleChange}>
{options.map(o => (<option value={o} selected={o == selectedValue}>{o}</option>)}
</select>
</label>
<input type="submit" value="Submit" />
It is because banana is not in options. If option's value is not present then it will by default pick the first one(Default behaviour). DEMO
import "./styles.css";
import { useState } from "react";
export default function App() {
const [value, setValue] = useState("mango");
const handleChange = (e) => {
setValue(() => {
return e.target.value;
});
};
return (
<div className="App">
<select value={value} onChange={handleChange}>
<option value="grapefruit">Grapefruit</option>
<option value="lime">Lime</option>
<option value="coconut">Coconut</option>
<option value="mango">Mango</option>
</select>
</div>
);
}

How to use defaultValue in the select tag in a functional component?

I have a functional component that contains a select tag with a few options.
I want to set cars as the default value.
Initially, I simply added selected in the car's option but react gave me a warning saying I should be using defaultValue in the select tag instead. I was wondering how I can do that?
Thanks in advance.
function ChooseOptions(props) {
return (
<div>
<h2>Choose Options</h2>
<label>
New Only <input type="checkbox" />
</label>
<label
htmlFor="selectType"
style={{ display: "block" }}
defaultValue="Cars"
>
Select Type
<select id="selectType">
<option value="all">All</option>
<option value="cars">Cars</option>
<option value="trucks">Trucks</option>
<option value="convertibles">Convertibles</option>
</select>
</label>
</div>
);
}
Try this.
You will get the change value in 'onChange' props,
You can set value by passing 'value' props
<select id="selectType" defaultValue="cars">
<option value="all">All</option>
<option value="cars">Cars</option>
<option value="trucks">Trucks</option>
<option value="convertibles">Convertibles</option>
</select>

In React, how can I use the same form for Create and Update functionality?

I have a form that I am using to Create a dog. I would also like to use this same form to update/edit that dog but I'm running into issues where I can't my input form is not editable (I think some type of race condition of what is getting updated and when).
Here is my original form that worked as expected to create a Dog:
import React from 'react'
import PropTypes from 'prop-types'
class CreateDogForm extends React.Component {
state = {
name: '',
ageInYears: "0",
ageInMonths: "0",
gender: null,
neuteredOrSpayed: null,
weightInLbs: "0",
bodyCondition: null,
activityLevel: null,
breeds: [],
}
handleChange = (e) => {
console.log('value:', e.target.value)
console.log('options:', e.target.options)
console.log('type:', e.target.type)
let value = e.target.value
if(e.target.type === 'number') {
value = parseInt(e.target.value)
}
this.setState({[e.target.name]: value})
}
handleSubmit = (e) => {
e.preventDefault()
const dog = {
name: this.state.name,
ageInYears: this.state.ageInYears,
ageInMonths: this.state.ageInMonths,
gender: this.state.gender,
neuteredOrSpayed: this.state.neuteredOrSpayed,
weightInLbs: this.state.weightInLbs,
bodyCondition: this.state.bodyCondition,
activityLevel: this.state.activityLevel,
breeds: this.state.breeds,
createdAt: new Date(),
createdBy: "kamtodo"
}
if (dog.name) {
this.props.createNewDog(dog)
} else {
alert('Please fix all errors. ')
}
}
render() {
return (
<form className="create-dog-wrapper" onSubmit={this.handleSubmit}>
<div>
<label>Dog's Name:</label><input type="text" name="name" placeholder="Dog name" required onChange={this.handleChange}/>
</div>
<div>
<label>Age:</label><input type="number" name="ageInYears" placeholder="(Years)" min="0" max="30" onChange={this.handleChange}/> and
<input type="number" name="ageInMonths" placeholder="(Months)" min="0" max="11" onChange={this.handleChange}/>
</div>
<div>
<label>Gender:</label>
<select name="gender" defaultValue="" required onChange={this.handleChange}>
<option disabled value=""> -- select an option -- </option>
<option value="male">Male</option>
<option value="female">Female</option>
</select>
</div>
<div>
<label>Neutered/Spayed:</label>
<select name="neuteredOrSpayed" defaultValue="" required onChange={this.handleChange}>
<option disabled value=""> -- select an option -- </option>
<option value="yes">Yes</option>
<option value="no">No</option>
</select>
</div>
<div>
<label>Weight:</label><input type="number" name="weightInLbs" required placeholder="(Pounds)" min="0" max="343" onChange={this.handleChange}/>
</div>
<div>
<label>Body Condition:</label>
<select name="bodyCondition" defaultValue="" required onChange={this.handleChange}>
<option disabled value=""> -- select an option -- </option>
<option value="underweight">Underweight</option>
<option value="correct_weight">Correct Weight</option>
<option value="overweight">Overweight</option>
</select>
</div>
<div>
<label>Activity Level:</label>
<select name="activityLevel" defaultValue="" required onChange={this.handleChange}>
<option disabled value=""> -- select an option -- </option>
<option value="low_activity">Low Activity</option>
<option value="normal_activity">Normal Activity</option>
<option value="high_activity">High Activity</option>
</select>
</div>
<div>
<label>Dog's Breed:</label>
<select name="breeds" defaultValue={[]} required multiple>
<option value="1c3b58ee-2fc7-40ad-bde2-99361373f0ec">Dalmatian</option>
<option value="2ec3b80a-b1c4-4cc6-b0c5-f3d20e574eaa">Maltese</option>
<option value="8a1ca2e2-13fc-4c6d-9944-5b102b04d287">Poodle</option>
</select>
</div>
<div>
<button type="submit">Create New Dog</button>
</div>
</form>
)
}
}
CreateDogForm.propTypes = {
createNewDog: PropTypes.func.isRequired
}
export default CreateDogForm
Here is what my new form to CreateOrUpdate a Dog looks like. When I display the form on the web I am not able to edit any fields (probably some kind of circular dependency issue):
import React from 'react'
import PropTypes from 'prop-types'
class CreateOrUpdateDogForm extends React.Component {
state = {
id: null,
name: '',
ageInYears: "0",
ageInMonths: "0",
gender: null,
neuteredOrSpayed: null,
weightInLbs: "0",
bodyCondition: null,
activityLevel: null,
breeds: [],
}
handleChange = (e) => {
console.log('value:', e.target.value)
console.log('options:', e.target.options)
console.log('type:', e.target.type)
let value = e.target.value
if(e.target.type === 'number') {
value = parseInt(e.target.value)
}
this.setState({[e.target.name]: value})
}
handleSubmit = (e) => {
e.preventDefault()
const dog = {
id: this.state.id,
name: this.state.name,
ageInYears: this.state.ageInYears,
ageInMonths: this.state.ageInMonths,
gender: this.state.gender,
neuteredOrSpayed: this.state.neuteredOrSpayed,
weightInLbs: this.state.weightInLbs,
bodyCondition: this.state.bodyCondition,
activityLevel: this.state.activityLevel,
breeds: this.state.breeds,
createdAt: new Date(),
createdBy: "kamtodo"
}
// #kamtood: Perform full validation here
// #kamtood: Perform casting from string to int in appropriate fields
if (dog.name) {
this.props.createNewDog(dog)
} else {
alert('Please fix all errors. ')
}
}
render() {
return (
<form className="create-dog-wrapper" onSubmit={this.handleSubmit}>
<input type="text" name="id" value={this.props.dogId ||''} readOnly/>
<div>
<label>Dog's Name:</label><input type="text" name="name" onChange={this.handleChange} value={this.props.dogData.name ||''} placeholder="Dog name" required />
</div>
<div>
<label>Age:</label><input type="number" name="ageInYears" onChange={this.handleChange} value={this.props.dogData.ageInYears || ''} placeholder="(Years)" min="0" max="30" /> and
<input type="number" name="ageInMonths" onChange={this.handleChange} value={this.props.dogData.ageInMonths || ''} placeholder="(Months)" min="0" max="11" />
</div>
<div>
<label>Gender:</label>
<select name="gender" onChange={this.handleChange} value={this.props.dogData.gender ||''} required>
<option disabled value=""> -- select an option -- </option>
<option value="male">Male</option>
<option value="female">Female</option>
</select>
</div>
<div>
<label>Neutered/Spayed:</label>
<select name="neuteredOrSpayed" onChange={this.handleChange} value={this.props.dogData.neuteredOrSpayed ||''} required>
<option disabled value=""> -- select an option -- </option>
<option value="yes">Yes</option>
<option value="no">No</option>
</select>
</div>
<div>
<label>Weight:</label><input type="number" name="weightInLbs" onChange={this.handleChange} value={this.props.dogData.weightInLbs ||''} required placeholder="(Pounds)" min="0" max="343" />
</div>
<div>
<label>Body Condition:</label>
<select name="bodyCondition" onChange={this.handleChange} value={this.props.dogData.weightInLbs ||''} required>
<option disabled value=""> -- select an option -- </option>
<option value="underweight">Underweight</option>
<option value="correct_weight">Correct Weight</option>
<option value="overweight">Overweight</option>
</select>
</div>
<div>
<label>Activity Level:</label>
<select name="activityLevel" onChange={this.handleChange} value={this.props.dogData.activityLevel ||''} required>
<option disabled value=""> -- select an option -- </option>
<option value="low_activity">Low Activity</option>
<option value="normal_activity">Normal Activity</option>
<option value="high_activity">High Activity</option>
</select>
</div>
<div>
<label>Dog's Breed:</label>
<select name="breeds" defaultValue={[]} required multiple>
<option value="1c3b58ee-2fc7-40ad-bde2-99361373f0ec">Dalmatian</option>
<option value="2ec3b80a-b1c4-4cc6-b0c5-f3d20e574eaa">Maltese</option>
<option value="8a1ca2e2-13fc-4c6d-9944-5b102b04d287">Poodle</option>
</select>
</div>
<div>
<button type="submit">Save</button>
</div>
</form>
)
}
}
CreateOrUpdateDogForm.propTypes = {
createNewDog: PropTypes.func.isRequired,
dogId: PropTypes.string,
dogData: PropTypes.object.isRequired,
}
export default CreateOrUpdateDogForm
Your component will only re-render when the props to it change or your internal state changes. Your form is using the props as values, and the props aren't changing when you type, so they stay the same.
You need to use your component's state for the input values. This is also known as controlled forms.
So instead of:
<div>
<label>Dog's Name:</label><input type="text" name="name" onChange={this.handleChange} value={this.props.dogData.name ||''} placeholder="Dog name" required />
</div>
do this:
<div>
<label>Dog's Name:</label><input type="text" name="name" onChange={this.handleChange} value={this.state.name ||''} placeholder="Dog name" required />
</div>
But of course for this to work you will need to map your incoming props to the component's state when it loads:
constructor(props) {
super(props);
this.state = {
xyx: props.dogData.xyz
...
}
}

Resources