How to pass values from dropdown to inputs on select ? ReactJS - reactjs

I don't know how to pass values from dropdown on select to 4 inputs. My dropdown showing address as it should be but I struggle to pass each value to separate inputs.e.g address_1 should be in one input where is flat number, address_2 where is street etc.
const [select,setSelect]=useState()
<select onChange={(e) => setSelect(e.target.value)}>
<option>Select Address</option>
{getAddressData?.address? (
getAddressData?.address?.map((address: any, id) => (
<option>{`${address.Address_1},${address.Address_2}, ${address.Town}, ${address.County}`}</option>
<input>
type={'text'}
name={'flatNumber'}
placeholder="Flat Number"
value={select}
</input>
Right now I have whole line of address e.g (30 Ballot Street,Smethick,West Midlands) in the whole one input.

Here's the working code. It's live here: https://codesandbox.io/s/competent-firefly-0qdrij?file=/src/App.js
import React, { useState, useEffect } from "react";
function App() {
const [address, setAddress] = useState({
Address_1: "",
Address_2: "",
Town: "",
pafCounty: ""
});
let getAddressData = {};
getAddressData.address = [
{
Address_1: "Address_1",
Address_2: "Address_2",
Town: "Town",
pafCounty: "pafCounty"
},
{
Address_1: "Address_11",
Address_2: "Address_22",
Town: "Town2",
pafCounty: "pafCounty2"
}
];
function handleChange(e) {
setAddress({ ...address, [e.target.name]: e.target.value });
}
useEffect(() => {
console.log(address);
}, [address]);
return (
<>
<select
onChange={(e) => {
setAddress(getAddressData?.address[e.target.value]);
}}
>
<option selected disabled>
Select Address
</option>
{getAddressData?.address?.map((address, index) => (
<option
key={index}
value={index}
>{`${address.Address_1}, ${address.Address_2}, ${address.Town}, ${address.pafCounty}`}</option>
))}
</select>
{Object.keys(address).map((key, index) => (
<input
type="text"
name={key}
placeholder="Flat Number"
value={address[key]}
onChange={handleChange}
/>
))}
</>
);
}
export default App;

Instead of setSelect(e.target.value), set it to the original structured address object. You could have the value of the option be the index within the address list, for example, and then setSelect(getAddressData?.address[2]) or whatever.

Related

React: Select component not updating inside a dynamic form

I am attempting to create a dynamic form in which there are 2 text fields and one dropdown select. These fields can be added by clicking the "Add More.." button. The remove button removes a particular field set. After an npm start the code shows all elements normally, add, remove and input fields work as intended. However, the problem starts when the select is used. On selecting something, the app crashes and gives a white screen with the errors [tag:"formFields.map is not a function"] and [tag:"Consider adding an error boundary to your tree to customize error handling behavior."] I would appreciate any help that can resolve this. :)
P.S. I am learning react through building projects rather than the conventional method of sitting through hours of tutorials and figuring things out. I am grateful to any help that is offered to me.
import { useState } from "react";
function FoodPreferences(){
const [formFields, setFormFields] = useState([
{ name: '', age: '', food: '' }
])
const [foodState, setFoodState] = useState("dumpling");
const handleFormChange = (event, index) => {
let data = [...formFields];
data[index][event.target.name] = event.target.value;
setFormFields(data);
}
const handleSelectChange = (event, index) => {
const selectedFood = event.target.value
setFormFields(selectedFood)
}
const submit = (e) => {
e.preventDefault();
console.log(formFields, foodState)
}
const addFields = () => {
let object = {
name: '',
age: '',
food: ''
}
setFormFields([...formFields, object])
}
const removeFields = (index) => {
let data = [...formFields];
data.splice(index, 1)
setFormFields(data)
}
return (
<div className="App">
<form onSubmit={submit}>
{formFields.map((form, index) => {
return (
<div key={index}>
<input
name='name'
placeholder='Name'
onChange={event => handleFormChange(event, index)}
value={form.name}
/>
<input
name='age'
placeholder='Age'
onChange={event => handleFormChange(event, index)}
value={form.age}
/>
<select
className="custom-select"
value={form.food}
onChange={event => handleSelectChange(event,index)}
>
<option value="steak">Steak</option>
<option value="sandwich">Sandwich</option>
<option value="dumpling">Dumpling</option>
</select>
<button onClick={() => removeFields(index)}>Remove</button>
</div>
)
})}
</form>
<button onClick={addFields}>Add More..</button>
<br />
<button onClick={submit}>Submit</button>
</div>
);
}
export default FoodPreferences;
I have tried using the select component alone without looping it and it worked fine. The errors pop up when select component is placed under a map() for dynamic inputs (Adding or Removing Fields). I know that the error is either in the onChange part of my code for the select component or the handleSelectChange
import React, {useState} from 'react';
function FoodChoice() {
const \[foodState, setFoodState\] = useState("dumpling");
return (
<div className="container p-5">
<select
className="custom-select"
value={foodState}
onChange={(e) => {
const selectedFood = e.target.value;
setFoodState(selectedFood);
}}
>
<option value="steak">Steak</option>
<option value="sandwich">Sandwich</option>
<option value="dumpling">Dumpling</option>
</select>
{foodState}
</div>
);
}
export default FoodChoice;

How to set an usestate with an object from another usestate array?

I need to set an usestate hook with the option selected from a datalist among another usestate array.
Here is my code :
import { useEffect, useState } from 'react';
export function ChooseCar() {
const [cars, setCars] = useState([]);
const [currentCar, setCurrentCar] = useState();
useEffect(() => {
declareCar();
}, [])
function declareCar() {
try {
setCars([]);
setCars(prev => [...prev, { _owner: "John", _brand: "Ferrari", _model: "F458" }]);
setCars(prev => [...prev, { _owner: "Jim", _brand: "Porsche", _model: "993" }]);
setCars(prev => [...prev, { _owner: "Joe", _brand: "Aston Martin", _model: "Vantage" }]);
console.log({ cars });
} catch (err) {
console.log(err);
}
}
function viewConsole() {
console.log(currentCar);
}
return (<div>
<label htmlFor="car-choice">Car :</label>
<input list="Car" id="car-choice" name="car-choice" onChange={e => setCurrentCar(e.target.value)} />
<datalist id="Car">
{cars.map(car => (
<option key={car._owner} value={car._owner}></option>
))}
</datalist>
<div>
<button onClick={declareCar}>Refresh</button>
<button onClick={viewConsole}>console</button>
</div>
<div>{currentCar}</div>
</div>)
}
I need to set my currentCar state with the selected car from the datalist. I'm able to set with car._owner or car._model, but not with the entire car object.
I hope I'm being explicit enough.
Thanks.
I tried to :
e => setCurrentCar(e.target.value)
with
value = car._owner
like in the example above. I tried to use :
<input list="Car" id="car-choice" name="car-choice" onChange={e => setCurrentCar(
e.target.owner,
e.target.brand,
e.target.model
)} />
<datalist id="Car">
{cars.map(car => (
<option key={car._owner} owner={car._owner} brand={car._brand} model={car._model} value={car._owner}></option>
))}
</datalist>
It resulted to currentCar = undefined.
I tried :
<label htmlFor="car-choice">Car :</label>
<input list="Car" id="car-choice" name="car-choice" onChange={e => setCurrentCar(e.target.value)} />
<datalist id="Car">
{cars.map(car => (
<option key={car._owner} value={car._owner} brand={car._brand} model={car}></option>
))}
</datalist>
But it resulted to [object Object]

how to get value in dynamic input to sql React

I'm a newbie react.I had generated input fields dynamically. Now I want to get values firstName and Lastname in this dynamics input fields to the database but I don't know how to get this value.
please help me
his my code App.js
import React, { useState } from "react";
function App() {
const [inputList, setInputList] = useState([{ firstName: "", lastName: "" }]);
const handleInputChange = (e, index) => {
const { name, value } = e.target;
const list = [...inputList];
list[index][name] = value;
setInputList(list);
};
const handleAddClick = () => {
setInputList([...inputList, { firstName: "", lastName: "" }]);
};
return (
<div className="App">
{inputList.map((x, i) => {
return (
<div className="box">
<input
name="firstName"
placeholder="Enter First Name"
value={x.firstName}
onChange={e => handleInputChange(e, i)}
/>
<input
className="ml10"
name="lastName"
placeholder="Enter Last Name"
value={x.lastName}
onChange={e => handleInputChange(e, i)}
/>
<div className="btn-box">
{inputList.length - 1 === i && <button onClick={handleAddClick}>Add</button>}
</div>
</div>
);
})}
<div style={{ marginTop: 20 }}>{JSON.stringify(inputList)}</div>
</div>
);
}
export default App;
Thank you
You need to retrieve values from server side which means you will do fetch process in browser side. Use useEffect to do fetch call and set the response with setInputList.
The below is one way with useEffect. Depending on your pj concept, you can also use useSwr, SSR or etc where data retrieving happens.
import React, { useState, useEffect } from "react";
function App() {
const [inputList, setInputList] = useState([{ firstName: "", lastName: "" }]);
const handleInputChange = (e, index) => {
const { name, value } = e.target;
const list = [...inputList];
list[index][name] = value;
setInputList(list);
};
const handleAddClick = () => {
setInputList([...inputList, { firstName: "", lastName: "" }]);
};
useEffect(()=>{
let canExexute = true;
// Anything to retrieve data such as
// fetch, graphql query,,,etc
// Set values from the above
if (canExecute) setInputList(values)
// Caring about when unmounting component
return ()=>{
canExecute = false;
}
// Don't put inputList state itself as dependancies which causes infinite rendering.
},[dependencies])
return (
<div className="App">
{inputList.map((x, i) => {
return (
<div className="box">
<input
name="firstName"
placeholder="Enter First Name"
value={x.firstName}
onChange={e => handleInputChange(e, i)}
/>
<input
className="ml10"
name="lastName"
placeholder="Enter Last Name"
value={x.lastName}
onChange={e => handleInputChange(e, i)}
/>
<div className="btn-box">
{inputList.length - 1 === i && <button onClick={handleAddClick}>Add</button>}
</div>
</div>
);
})}
<div style={{ marginTop: 20 }}>{JSON.stringify(inputList)}</div>
</div>
);
}
export default App;

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
});
};

How to update select items based on the selection from the first select items using react

I have an array of objects like this:
const items = [
{ country:"USA", level:1},
{ country:"Canada", level:2},
{ country:"Bangladesh", level:3},
]
And in my Form component( I am using React Formik library)I am rendering the items like this:
<Field name="color" as="select" placeholder="Favorite Color">
{items.map((item,index)=>(
<option>{item.country}</option>
))}
</Field>
<Field name="color" as="select" placeholder="Favorite Color">
{items.map((item,index)=>(
<option>{item.level}</option>
))}
</Field>
Now,I need to update the value of second select items based on the items selection from the first select input. For example, when I will select "USA" from the first selection then in the second selection it will update the value and render "1". Any ideas or suggestion would be highly appreciated.
So far, my component looks like this:
import React from 'react';
import { Formik, Field } from 'formik';
import { Modal } from 'react-bootstrap';
const AddNewForm = () => {
const items = [
{ country:"USA", level:1},
{ country:"Canada", level:2},
{ country:"Bangladesh", level:3},
]
const handleUpdate = () => {
console.log("change value...")
}
return (
<div>
<Formik
initialValues={{ country: '', level: '' }}
onSubmit={(values, { setSubmitting }) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
setSubmitting(false);
}, 400);
}}
>
{({
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
isSubmitting,
/* and other goodies */
}) => (
<form onSubmit={handleSubmit}>
<Field name="country" as="select" onChange={handleUpdate}>
{items.map((item,index)=>(
<option>{item.country}</option>
))}
</Field>
<Field name="level" as="select">
{items.map((item,index)=>(
<option>{item.level}</option>
))}
</Field>
<Modal.Footer>
<button type="submit" disabled={isSubmitting}>
Save
</button>
</Modal.Footer>
</form>
)}
</Formik>
</div>
)
}export default AddNewForm;
As I wrote earlier ... there is no need to manage states manually, Formik manages it for us.
Version with functional conponents/hooks - useFormikContext (and <Formi /> as parent/context provider) is needed when <Field/> is used. You can use useFormik (and no parent) with normal html inputs.
Outer component:
export default function App() {
const items = [
{ country: "USA", level: 1 },
{ country: "USA", level: 5 },
{ country: "Canada", level: 2 },
{ country: "Canada", level: 4 },
{ country: "Bangladesh", level: 2 },
{ country: "Bangladesh", level: 7 }
];
return (
<div className="App">
<h1>connected selects</h1>
<Formik
initialValues={{ country: "", level: "" }}
onSubmit={values => {
console.log("SUBMIT: ", values);
}}
>
<Form data={items} />
</Formik>
</div>
);
}
Outer component (parent <Formik />) responsibility:
initialization
main handlers (submit)
validation
Inner component responsibility:
data passed as prop;
local data filtering (avoiding unnecessary recalculations with hooks);
local handlers for field dependencies;
visual conditional changes
Inner component:
import React, { useState, useEffect } from "react";
import { Field, useFormikContext } from "formik";
import { Modal } from "react-bootstrap";
const AddNewForm = props => {
const items = props.data;
// derived data, calculated once, no updates
// assuming constant props - for changing useEffect, like in levelOptions
const [countryOptions] = useState(
Array.from(new Set(items.map(item => item.country)))
);
const [levelOptions, setLevelOptions] = useState([]);
const {
values,
handleChange,
setFieldValue,
handleSubmit,
isSubmitting,
isValid // will work with validation schema or validate fn defined
} = useFormikContext();
const myHandleChange = e => {
const selectedCountry = e.target.value;
debugger;
// explore _useFormikContext properties
// or FormikContext in react dev tools
console.log("myHandle selectedCountry", selectedCountry);
handleChange(e); // update country
// available levels for selected country
const levels = items.filter(item => item.country === selectedCountry);
if (levels.length > 0) {
// update level to first value
setFieldValue("level", levels[0].level);
console.log("myHandle level", levels[0].level);
}
};
// current values from Formik
const { country, level } = values;
// calculated ususally on every render
//
// const countryOptions = Array.from(new Set(items.map(item => item.country)));
// const levelOptions = items.filter(item => item.country === country);
//
// converted into hooks (useState and useEffect)
//
useEffect(() => {
// filtered array of objects, can be array of numbers
setLevelOptions(items.filter(item => item.country === country));
}, [items, country]); // recalculated on country [or items] change
return (
<div>
<form onSubmit={handleSubmit}>
<Field
name="country"
value={country}
as="select"
onChange={myHandleChange} // customized handler
>
{!country && (
<option key="empty" value="">
Select Country - disappearing empty option
</option>
)}
{countryOptions.map((country, index) => (
<option key={country} value={country}>
{country}
</option>
))}
</Field>
{country && (
<>
<Field
name="level"
as="select"
onChange={handleChange} // original handler
>
{levelOptions.map((item, index) => (
<option key={item.level} value={item.level}>
{item.level}
</option>
))}
</Field>
<Modal.Footer>
<button type="submit" disabled={!isValid && isSubmitting}>
Save
</button>
</Modal.Footer>
</>
)}
</form>
<>
<h1>values</h1>
{country && country}
<br />
{level && level}
</>
</div>
);
};
export default AddNewForm;
Working demo, explorable/debbugable iframe here
Does it fulfill all functional requirements ?
Try this.
import React, {useState} from "react";
import { Formik, Field } from "formik";
import { Modal } from "react-bootstrap";
const AddNewForm = () => {
const items = [
{ country: "USA", level: 1 },
{ country: "Canada", level: 2 },
{ country: "Bangladesh", level: 3 },
];
return (
<div>
<Formik
initialValues={{ country: "", level: "" }}
onSubmit={(values, { setSubmitting }) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
setSubmitting(false);
}, 400);
}}
>
{({
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
isSubmitting
/* and other goodies */
}) => (
<form onSubmit={handleSubmit}>
<Field name="country" as="select" onChange={handleChange} >
<option value='' defaultValue>Select Country</option>
{items.map((item, index) => (
<>
<option value={item.country} >{item.country}</option>
</>
))}
</Field>
<Field name="level" as="select" onChange={handleChange} >
<option value='' defaultValue>Select Level</option>
{items.filter((item)=>item.country===values.country).map((item, index) => (
<option>{item.level}</option>
))}
</Field>
<Modal.Footer>
<button type="submit" disabled={isSubmitting}>
Save
</button>
</Modal.Footer>
</form>
)}
</Formik>
</div>
);
};
export default AddNewForm;
Try this working demo

Resources