How Can I create a Handle an input object with React hooks - reactjs

I have problem in my input object how can I change the onChage function this is my input code
<Form.Group as={Col} controlId="formGridResultat">
<Form.Label>Result</Form.Label>
<Form.Control required as="select"
type="text"
id="conduexam.id"
name="conduexam.id"
value={currentStates. conduexam?.nom}
className={"bg-white text-dark"}
onChange={handleInputChange}>
<option value="">Choisir un Resultat </option>
{result.map((value) => (
<option value={value.id} key={value.id}>
{value.nom}
</option>
))}
</Form.Control>
</Form.Group>
The function “onChange” how can I change it?
const handleInputChange = event => {
const { name, value } = event.target;
setCurrentStates({ ...currentStates, [name]: value });
};

Try this:
const [currentStates, setCurrentStates]= useState({
//your initial code here
})
const handleInputChange = event => {
console.log(event.target.value)
setCurrentStates({ ...currentStates, [name]: event.target.value});
};

Related

Why do I need a separate handler from checked input?

Unable to get the value of the checked input (true or false).
function Login() {
const [inputs, setInputs] = useState({});
const handleChange = (event) => {
const name = event.target.name;
const value = event.target.value;
setInputs(values => ({
...values,
[name]: value
}));
};
const handleSubmit = (event) => {
event.preventDefault();
console.log({inputs});
};
return (
<form onSubmit={handleSubmit}>
<input type="email" name="mail" value={inputs.mail || ""} onChange={handleChange}/>
<input type="password" name="pass" value={inputs.pass || ""} onChange={handleChange}/>
<div>
<input type="checkbox" name="check" value={inputs.check || false} onChange={handleChange}/>
<label>Remember me</label>
</div>
<button type="submit">Submit</button>
</form>
);
}
export default LoginGoogle
Tried
const handleChange = (event) => {
const name = event.target.name;
const value = event.target.value;
const check = event.target.checked;
setInputs(values => ({
...values,
[name]: value || check
}));
};
For
<input type="checkbox" name="check" value={inputs.checked} onChange={handleChange}/>
And
<input type="checkbox" name="check" checked={inputs.checked} onChange={handleChange}/>
It works, but I am certain I am going about it wrong. Tutorials seem to concentrate on input objects of similar key-values, e.g. multiple checkboxes, multiple text input, and so on.
The reason is that checkbox values never change, only their checked property does.
Ideally, you'd use a different change handler
const onCheckboxChange = ({ target: { name, checked } }) => {
setInputs((prev) => ({
...prev,
[name]: checked,
}));
};
return (
<input
type="checkbox"
name="check"
checked={inputs.check}
onChange={onCheckboxChange}
/>
);

Dont set value in Form.Control

I have a new form for save data.
I use this code
const [validated, setValidated] = useState(false);
const [newInfo, setNewInfo] = useState({
name: ""
});
const handleChange = (event) => {
const { name, value }=event.target.value;
setNewInfo({
...newInfo,
[name]: value
});
console.log(newInfo.name)
};
and in Form.Control
<Form noValidate validated={validated}>
<Form.Group >
<Form.Label>Name</Form.Label>
<Form.Control required type="text" placeholder="Enter Name" value={newInfo.name}
onChange={handleChange} />
<Form.Control.Feedback type="invalid">Please choose a name.</Form.Control.Feedback>
</Form.Group>
<Button onClick={(e) => handleSubmit(e)} variant="primary">Submit</Button>
</Form>
When i type in input, run onchangehandle and event.target.value has value but dont set in input (input is empty) !!
when i change const [newInfo, setNewInfo] = useState(""); and set a string for it, it is ok .
setNewInfo() which is a setter is asynchronous, which means that at the time you console.log the state, it's not updated yet.
You can use useEffect to track for changes of state.
useEffect(() => {
console.log(newInfo);
},[newInfo.name);

how to handle multiple form input with dynamic dropdown render in react Js

I have created a form with multiple input there two dropdown first has option and second one's option changes dynamically based on selection of first dropdown. also i am storing all values in state with submit event.
Okay problem is i am either able to to get values and in state on submit event or either able to dynamically change the option for second dropdown.
But when I am trying to do both or trying to run two function on same onChange event its not trigging is any one can help me out why its not getting trigger and what is the issue.
link : if any one want to see code it dummy code
https://codesandbox.io/s/clever-mendel-ozt8tu?file=/src/App.js:0-1748
App.js
import "./styles.css";
import { useState } from "react";
function App() {
const data = {
first: ["car", "bus"],
second: ["bike", "train"],
third: ["plane", "rocket"]
};
const [option, setOption] = useState([]);
const getInput = (e) => {
let input = e.target.value;
setOption(data[input]);
};
const [values, setValues] = useState({
name: "",
city: "",
category: "",
ride: ""
});
const inputHandle = (e) => {
const { name, value } = e.target;
setValues({
...values,
[name]: value
});
};
const handleSubmit = (e) => {
e.preventDefault();
console.log(values);
};
return (
<>
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="name"
name="name"
value={values.name}
onChange={inputHandle}
/>
<input
type="text"
placeholder="city"
name="city"
value={values.city}
onChange={inputHandle}
/>
<br />
<select
name="category"
values={values.category}
onChange={(e) => {
getInput();
inputHandle();
}}
>
<option defaultValue="category">category</option>
<option value="first">first</option>
<option value="second">Second</option>
<option value="third">Third</option>
</select>
<select name="ride" value={values.ride} onChange={inputHandle}>
{option.map((ele) => (
<option value={ele}>{ele}</option>
))}
</select>
<br />
<button type="submit">Submit</button>
</form>
</>
);
}
export default App;
For the handler of the onChange in the first select, you are taking in the event object e as parameter but not passing it forward in getInput() or inputHandle(). Therefore, you should write something like this:
onChange={(e) => {
getInput(e);
inputHandle(e);
}}
This should do the job. Also, try to use only one function in the handler, like the one you have used for submitting the form.
If you want to combine everything into one handler, you can use the following handler:
const categoryHandler = (event) => {
const selectName = event.target.name;
const selectValue = event.target.value;
setOption(data[selectValue]);
setValues({
...values,
selectName: selectValue
});
};

Set value in Select (Input) of reactstrap

Code:
const [frequency, setFrequency] = useState({});
function handleSelect(event) {
const target = event.target;
const value = target.value;
const name = target.name;
setFrequency({
...frequency,
[name]: value
})
}
<FormGroup>
<Label for="exampleSelect">Select</Label>
<Input type="select" name="select" id="exampleSelect" onChange= {handleSelect} >
// I tried the below, But it does not seem to work
<Input type="select" name="frequency" id="frequency" value={frequency.frequency}>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</Input>
</FormGroup>
Dropdown:
Selected value:
When I select the value it renders in the input but when I want to set the selected value.
Meaning, I want to set the value such that when I load it should start from a selected value not from 1.
So how can I set the value?
I can setState by calling some select function. But in input tag I just want a value any value so when I refresh dropdown should show xyx...1,2,3,4.
If you write value="xyx", the value of select will always be xyz no matter what option you select.
So, instead of that you can provide value from react state and a handleChange function to change the value on select.
If you want to select the "first option" i.e. xyz at start, you can initialize the state with xyz:
export default function App() {
const [frequency, setFrequency] = useState({ frequency: "xyz" });
function handleSelect(e) {
setFrequency((prev) => ({
...prev,
[e.target.name]: e.target.value,
}))
}
return (
<>
{JSON.stringify(frequency)}
<FormGroup>
<Label for="exampleSelect">Select</Label>
<Input
type="select"
name="frequency"
id="frequency"
value={frequency.frequency}
onChange={handleSelect}
>
<option>xyz</option>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</Input>
</FormGroup>
</>
);
}
Here is a demo

How to add validation in Product add Form c- react component

I am doing Form for add product to firebase, but each click on the submit button, although it already has data or not, it still can add in Firebase. I would like to add validation to this case. How could I do that. I would like all file input cannot be left blank, and text file is always text not the number
const ProductForm = ({
products,
createProductRequest,
fetchProductRequest,
loading,
type }) => {
const [values, setValues] = useState({
image: "",
name: "",
price: 0,
description: "",
categoty: "",
});
const [imageAsFile, setImageAsFile] = useState();
useEffect(() => {
if (Object.keys(products).length) {
setValues(products);
}
}, [products]);
useEffect(() => {
if (type === "CREATE_PRODUCT_SUCCESS") {
fetchProductRequest();
}
}, [fetchProductRequest, type]);
const handleInputChange = (event) => {
// Create new product to update
const newPropdudct = {
...values,
[event.target.name]: event.target.value,
};
// Update new product for value
setValues(newPropdudct);
};
const handleFileChange = (event) => {
const image = event.target.files[0]
setImageAsFile(imageAsFile => (image))
console.log(image);
}
const onSave = () => {
createProductRequest(values, imageAsFile);
};
if (loading) {
return (
<Container>
<Loading />
</Container>
);
}
return (
<Container className="product-form">
<Form>
<Form.Group>
<Form.Group>
<Form.File
id="image"
label="Image choose"
value={values.image.name}
onChange={handleFileChange}
/>
</Form.Group>
</Form.Group>
<Form.Group controlId="name">
<Form.Label>Name</Form.Label>
<Form.Control
type="text"
placeholder="Enter product name"
value={values.name}
name="name"
onChange={handleInputChange}
>
</Form.Control>
</Form.Group>
<Form.Group controlId="categories">
<Form.Label>Categories</Form.Label>
<Form.Control
as="select"
name="category"
value={values.category}
onChange={handleInputChange}
>
{CATEGORIES.map((category, index) => (
<option key={index}>{category.name}</option>
))}
</Form.Control>
</Form.Group>
<Form.Group controlId="price">
<Form.Label>Price</Form.Label>
<Form.Control
type="number"
placeholder="Enter product price"
value={values.price}
name="price"
onChange={handleInputChange}
/>
</Form.Group>
<Form.Group controlId="description">
<Form.Label>Description</Form.Label>
<Form.Control
as="textarea"
rows="3"
name="description"
value={values.description}
onChange={handleInputChange}
/>
</Form.Group>
<Button btnText="Submit" size="btn-md" handleClick={onSave} />
</Form>
</Container>
);
};
export default ProductForm;
You may start by adding the required attribute to each form control for basic HMTL5 validation.
For more advanced validation logic, you can have this as your onSave content:
const onSave = (event) => {
let invalid = [];
['name', 'description', 'category'].forEach(key => {
if (values[key].match(/[0-9]+/))
invalid.push(key);
});
if (values.name.trim() === '')
invalid.push('name');
if (invalid.length !== 0) {
event.preventDefault();
// Whatever you want to do when the content is invalid
} else {
createProductRequest(values, imageAsFile);
}
};
With this snippet, you have the invalid fields in the invalid array variable.
You can also customize the validation logic.

Resources