save values of arrays inside a state from different input fields - arrays

i want to get the values from 5 input fields and save them inside a single state of arrays , how can i achieve that ?
const [features,setFeatures] = useState([]);
const handleChange = e => {
setFeatures(prev => ({ ...prev, features, [e.target.name]: e.target.value }))
}
<Input type="text" name="features" label="Feature 1" value={features} required change={handleChange} />
<Input type="text" name="features" label="Feature 2" value={features} required change={handleChange} />
<Input type="text" name="features" label="Feature 3" value={features} required change={handleChange} />
<Input type="text" name="features" label="Feature 4" value={features} required change={handleChange} />
<Input type="text" name="features" label="Feature 5" value={features} required change={handleChange} />

You can check the below implementation
Note that I hardcoded the array length and I'd assume your input array is static. If your input array is dynamic, you can use iteration for generating input fields. Besides that, I modified Input to input and change to onChange for the primitive input element. The button and form are for demo only.
const App = () => {
const [features,setFeatures] = React.useState(new Array(5));
const handleChange = (e,index) => {
const updatedFeatures = [...features] //clone data
updatedFeatures[index] = e.target.value
setFeatures(updatedFeatures)
}
const handleSubmit = (e) => {
e.preventDefault();
console.log(features);
}
return (<form onSubmit={handleSubmit}><input type="text" name="features" label="Feature 1" value={features[0]} required onChange={(e) => handleChange(e, 0)} />
<input type="text" name="features" label="Feature 2" value={features[1]} required onChange={(e) => handleChange(e, 1)} />
<input type="text" name="features" label="Feature 3" value={features[2]} required onChange={(e) => handleChange(e, 2)} />
<input type="text" name="features" label="Feature 4" value={features[3]} required onChange={(e) => handleChange(e, 3)} />
<input type="text" name="features" label="Feature 5" value={features[4]} required onChange={(e) => handleChange(e, 4)} />
<button type="submit">Submit</button>
</form>)
}
ReactDOM.render(
<App/>,
document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Related

input value's last letter won't be saved in local storage

I want to have a form and save the values on local storage.
when I did the same thing in Welcome component without writing another component for input, I got the exact result that I wanted.
but since I didn't want to write two different handleChange functions, I decided to create another component for Input. However, input's value is not saved completely on localstorage, the last letter is missing.
Why does this happen?
function Welcome () {
return(
<div className={`container ${styles.container}`}>
<form>
<label htmlFor="first_name"> First Name: </label>
<br />
<Input type="text" id="first_name" name="firstName" />
<br />
<label htmlFor="last_name"> Last Name: </label>
<br />
<Input type="text" id="last_name" name="lastName" />
<br />
<button type="submit" className={styles.btn}> Enter </button>
</form>
</div>
);
}
function Input ({name, type, id}) {
const [input, setInput] = useState("");
const handleChange = (e) => {
setInput(e.target.value);
localStorage.setItem(name, input);
}
return <input type={type} id={id} required onChange={handleChange} />
}

React : retrieve the state of a child component

I am trying to retrieve the value of the input in my Input component, to assign it to my user object in the parent component.
Here is my user object and my JSX:
const Form = ({ form }) => {
const [inputValue, setInputValue] = useState("");
const user = {
user_firstname: "OO",
user_lastname: "OO",
user_email: "lOOl0jyyv",
user_password: "OO"
};
return (
<form className="form" onSubmit={callApi}>
<Input
key={uuidv4()}
className="input_container"
type="text"
placeholder="Prénom"
id="firstname"
name="firstname"
min="2"
max="40"
/>
<Input
key={uuidv4()}
className="input_container"
type="text"
placeholder="Nom"
id="lastname"
name="lastname"
min="2"
max="60"
/>
<Input
key={uuidv4()}
className="input_container"
type="email"
placeholder="Votre adresse mail"
id="email"
name="email"
/>
<Input
key={uuidv4()}
className="input_container"
type="password"
placeholder="Mot de passe"
id="password"
name="password"
min="10"
max="32"
/>
<Input
key={uuidv4()}
className="input_container"
type="password"
placeholder="Confirmez le mot de passe"
id="verify-password"
name="verify-password"
min="10"
max="32"
/>
<Button name="Inscription" />
</form>
);
};
Each has its own state, I would like to be able to retrieve it from the parent component to assign them to my "user" object. This is my Input component :
const Input = ({
className,
type,
id,
name,
placeholder,
min,
max,
icon1,
icon2
}) => {
const inputHandler = e => {
setInputValue(e.target.value);
};
const [inputValue, setInputValue] = useState("");
return (
<div className={className}>
<input
className="testt"
type={type}
id={id}
name={name}
placeholder={placeholder}
minLength={min}
maxLength={max}
required
value={inputValue}
onChange={inputHandler}
/>
{icon1 && (
<div className="icons_container">
<FontAwesomeIcon icon={icon1} />
<FontAwesomeIcon icon={icon2} />
</div>
)}
</div>
);
};
Why not define the state in the parent element, then pass a reference to the state in the props of the child? In your case, place the input state of all the <Input /> components in the <Form /> component and pass each state to its respective input field.
You can pass onChange handler function as a prop from parent to child. This function will set value for user when child (Input) component invokes the function.
Changes needed for parent component:
...
const [user, setUser] = React.useState({
user_firstname: "OO",
user_lastname: "OO",
user_email: "lOOl0jyyv",
user_password: "OO"
});
return (
<form className="form" onSubmit={callApi}>
<Input
key={uuidv4()}
className="input_container"
type="text"
placeholder="Prénom"
id="firstname"
name="firstname"
min="2"
max="40"
onChange={value => setUser({ ...user, user_firstname: value })}
/>
...
Changes needed for Input component:
const Input = ({
className,
type,
id,
name,
placeholder,
min,
max,
icon1,
icon2,
onChange
}) => {
const inputHandler = e => {
setInputValue(e.target.value);
onChange(e.target.value);
};
...

Can't input on other Form Fields

I'm using react. I was wondering on why can I only edit the FirstName part of the form while the other input fields wont let me type anything.
Here is my code:
import React, {useContext, useState, useEffect} from 'react';
import{GlobalContext} from '../context/GlobalState';
import {Link, useHistory} from 'react-router-dom';
import {Form,FormGroup,Label,Input,Button} from 'reactstrap';
export const EditUser = (props) => {
const {users,editEmployee } = useContext(GlobalContext);
const [selectedUser, setSelectedUser] = useState({
id:'',
name:'',
nameL:'',
email:'',
contact:'',
address:'',
date:'',
});
const history= useHistory();
const currentUserId = props.match.params.id;
useEffect(() =>{
const userId =(currentUserId);
const selectedUser =users.find(user=>user.id === userId)
setSelectedUser(selectedUser)
}, [currentUserId,users])
const onChange = (e) =>{
setSelectedUser({...selectedUser, [e.target.name]: e.target.value})
}
const onNameL = (e) =>{
setSelectedUser({...selectedUser, [e.target.nameL]: e.target.value})
}
const onEmail = (e) =>{
setSelectedUser({...selectedUser, [e.target.email]: e.target.value})
}
const onContact = (e) =>{
setSelectedUser({...selectedUser, [e.target.contact]: e.target.value})
}
const onAddress = (e) =>{
setSelectedUser({...selectedUser, [e.target.address]: e.target.value})
}
const onDate = (e) =>{
setSelectedUser({...selectedUser, [e.target.date]: e.target.value})
}
const onSubmit= () =>{
editEmployee(selectedUser)
history.push('/');
}
return (
<React.Fragment>
<Form onSubmit={onSubmit}>
<FormGroup>
<Label>FirstName</Label>
<Input type="text" name="name" value={selectedUser.name} onChange={onChange} placeholder="enter first name"></Input>
<Label>Last Name:</Label>
<Input type="text" name="nameL" value= {selectedUser.nameL} onChange={onNameL} placeholder="enter your Last name"></Input>
<Label>Email:</Label>
<Input type="email" name="email" value= {selectedUser.email} onChange={onEmail} placeholder="Email Address"></Input>
<Label>Contact Number:</Label>
<Input type="number" name="contact" value= {selectedUser.contact} onChange={onContact} placeholder="Contact"></Input>
<Label>Address:</Label>
<Input type="text"name="address" value= {selectedUser.address} onChange={onAddress} placeholder="enter your Address"></Input>
<Label>Date</Label>
<Input type="date" name="date" value= {selectedUser.date} onChange={onDate} placeholder="enter date employed"></Input>
</FormGroup>
<Button type="submit" className="btn btn-info">Edit </Button>
<Link to="/" className="btn btn-danger">Cancel</Link>
</Form>
</React.Fragment>
)
}
export default EditUser;
In all the functions which are being used to control form fields, use the following code:
setSelectedUser({...selectedUser, [e.target.name]: e.target.value})
Also, you can just use a single function i.e. onChange, for the current implementation. There is no use in using multiple functions.
Welcome to the Stack Overflow Community !!!
You can do that using fewer lines of code in a very optimized manner like this. It will fix your error & make it easier to debug. Try this out.
// necessary imports
export const EditUser = (props) => {
const [selectedUser, setSelectedUser] = useState({
id: "",
name: "",
nameL: "",
email: "",
contact: "",
address: "",
date: "",
});
const onChange = (e) => {
const property = e.target.name;
const value = e.target.value;
setSelectedUser({
...selectedUser,
[property]: value,
});
}; // Just have only one event for all form elements.
return (
<React.Fragment>
<Form>
<FormGroup>
<Label>FirstName</Label>
<Input
type="text"
name="name"
value={selectedUser.name}
onChange={onChange}
placeholder="enter first name"
></Input>
<Label>Last Name:</Label>
<Input
type="text"
name="nameL"
value={selectedUser.nameL}
onChange={onChange}
placeholder="enter your Last name"
></Input>
<Label>Email:</Label>
<Input
type="email"
name="email"
value={selectedUser.email}
onChange={onChange}
placeholder="Email Address"
></Input>
<Label>Contact Number:</Label>
<Input
type="number"
name="contact"
value={selectedUser.contact}
onChange={onChange}
placeholder="Contact"
></Input>
<Label>Address:</Label>
<Input
type="text"
name="address"
value={selectedUser.address}
onChange={onChange}
placeholder="enter your Address"
></Input>
<Label>Date</Label>
<Input
type="date"
name="date"
value={selectedUser.date}
onChange={onChange}
placeholder="enter date employed"
></Input>
</FormGroup>
<Button type="submit" className="btn btn-info">
Edit{" "}
</Button>
</Form>
</React.Fragment>
);
}
Let me know if you need further support.

React/Hooks extra undefined field upon submission

I'm getting a really weird return error that on submission I randomly add an extra duplicate field somehow which is of course then undefined. The input value is also randomly copied from one of the other fields within the form.
const GameForm = () => {
const url = 'http://localhost:6060/games'
const handleInputChange = e => {
const { name, value, year, rating, developer } = e.target
setGameData({ ...gameData, [name]: value, [year]: value, [rating]: value, [developer]: value })
}
const onSubmit = (e) => {
e.preventDefault()
const { name, year, rating, developer } = gameData
if (!name || !year || !rating || !developer) return
console.log(gameData)
axios
.post(url, gameData)
.then((res) => {
setGameData(res)
}).catch((error) => console.log(error))
}
const [gameData, setGameData] = useState({ name: '', year: 0, rating: '', developer: "" })
return (
<form onSubmit={onSubmit}>
<label id="name" htmlFor="name">Name: </label>
<input type="text" name="name" placeholder="Game title" onChange={handleInputChange} />
<br />
<label htmlFor="year">Year: </label>
<input type="number" name="year" placeholder="Release year" onChange={handleInputChange} />
<br />
<label htmlFor="rating">Rating: </label>
<input type="text" name="rating" placeholder="Age rating" onChange={handleInputChange} />
<br />
<label htmlFor="developer">Developer: </label>
<input type="text" name="developer" placeholder="Developer" onChange={handleInputChange} />
<br />
<input type="submit" value="Submit"></input>
</form>
)
}
Console logged return: (I also get a 500 error obviously)
{name: "1", year: "1", rating: "1", developer: "1", undefined: "1"}
The undefined value is seemingly taken from any of the existing fields at random.
I feel like I am likely overlooking something obvious.
You are mis-using e.target. It will not have all the properties that you try to destruct from it. From the ones you list in your example code, it will only have name and value, all the other ones (rating, year, developer) will be undefined as they are not part of the event's target property.
The reason you only get one undefined value in your state object is because it keeps overriding itself when you set your state.
The property from the event target you are trying to access is name, so in your case basically e.target.name
Anyway, with that in mind the fix for your app will be quite simple:
const handleInputChange = e => {
const { name, value } = e.target
// Note: The name will hold whatever value of the name prop you put on your input.
// When you are editing the input with the name prop set to name, it will be "name"
// For the input with the name prop set to "year", it will be "year:
// For the input with the name prop set to "developer" it will be "developer" and so on.
setGameData({ ...gameData, [name]: value })
}
Here is a demo for you with the fix:
const App = () => {
const [gameData, setGameData] = React.useState({ name: '', year: 0, rating: '', developer: "" })
const handleInputChange = e => {
const { name, value } = e.target
setGameData({ ...gameData, [name]: value })
}
return (
<div>
<label id="name" htmlFor="name">Name: </label>
<input type="text" name="name" placeholder="Game title" onChange={handleInputChange} />
<br />
<label htmlFor="year">Year: </label>
<input type="number" name="year" placeholder="Release year" onChange={handleInputChange} />
<br />
<label htmlFor="rating">Rating: </label>
<input type="text" name="rating" placeholder="Age rating" onChange={handleInputChange} />
<br />
<label htmlFor="developer">Developer: </label>
<input type="text" name="developer" placeholder="Developer" onChange={handleInputChange} />
<br />
<button onClick={() => console.warn('GAME DATA OBJECT', gameData)}>Click</button>
</div>
)
}
ReactDOM.render(
<App />,
document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>

How to use innerRef in ReactStrap ? #TypeError: Cannot read property 'username' of undefined

I want to fetch form data from innerRef in Reactstrap. But I am getting TypeError: Cannot read property 'username' of undefined
Code
<FormGroup>
<Label htmlFor="username"> Username</Label>
<Input
innerRef={(input) => (this.username.value = input)}
type="text"
name="username"
id="username"
/>
</FormGroup>
ErrorScreenshot
You can do something like this;
For stateless function component:
const Header = () => {
let username: any;
let password: any;
let checkbox: any;
const handleLogin = (event: any) => {
console.log(
"Username" +
username?.value +
"Password" +
password?.value +
"Checkbox" +
checkbox?.value
);
event.preventDefault();
};
return (
<Form onSubmit={handleLogin}>
<FormGroup>
<Label htmlFor="username">Username</Label>
<Input
type="text"
id="username"
name="username"
innerRef={(x) => (username = x)}
/>
</FormGroup>
<FormGroup>
<Label htmlFor="password">Password</Label>
<Input
type="password"
id="password"
name="password"
innerRef={(x) => (password = x)}
/>
</FormGroup>
<FormGroup check>
<Label>Remember</Label>
<Input type="checkbox" name="remember" innerRef={(x) => (checkbox = x)} />
</FormGroup>
<Button className="bg-primary" type="submit" name="submit">
Login
</Button>
</Form>
);
};

Resources