react input form returns undefined - javascript

it updates only the lastly typed input box value in the state and other are undefined
i get this in console
Object { Name: undefined, Age: "123", City: undefined }
second time
Object { Name: undefined, Age: undefined, City: "city" }
Form.jsx
import React, {useState} from 'react';
const Form = (props) => {
const [formData, setFormData] = useState({ Name:'', Age:'', City:''});
const infoChange = e => {
const { name,value} = e.target;
setFormData({
[e.target.name]: e.target.value,
})
}
const infoSubmit = e =>{
e.preventDefault();
let data={
Name:formData.Name,
Age:formData.Age,
City:formData.City
}
props.myData(data);
}
return (
<div className="">
<form onSubmit={infoSubmit} autoComplete="off">
<div className="form-group mb-6">
<label className="">Name:</label>
<input type="text" onChange={infoChange} name="Name" value={formData.Name} className=""placeholder="Enter Name" />
</div>
<div className="form-group mb-6">
<label className="">City:</label>
<input type="text" onChange={infoChange} name="City" value={formData.City} className=""
placeholder="Enter Age" />
</div>
<button type="submit" className="">Submit</button>
</form>
</div>
);
};
export default Form;
App.jsx
this is App.jsx file, here i get the data prop and display it in console.log
import React from 'react';
import Form from './components/Form';
import Table from './components/Table';
const App = () => {
const create = (data) => {
console.log(data);
}
return (
<div className='flex w-full'>
<div className=''>
<Form myData={create} />
</div>
<div className=''>
<Table />
</div>
</div>
);
};
export default App;

You're stomping the previous state with the most recent change. If you want to preserve the existing state you have to include it in the update.
setFormData({
...formData,
[e.target.name]: e.target.value,
})

with react-hooks you need to set the entire object again.
const [formData, setFormData] = useState({ Name:'', Age:'', City:''});
const infoChange = e => {
const { name,value} = e.target;
setFormData({
// spread the current values here
...formData,
// update the current changed input
[name]: value,
})
or, even better IMHO. You have one state for each prop
const [name, setName] = useState('');
const [age, setAge] = useState('');
const [city, setCity] = useState('');
// ...
<input onChange={({target: {value}}) => setName(value)} />
<input onChange={({target: {value}}) => setAge(value)} />
<input onChange={({target: {value}}) => setCity(value)} />

Change this
const infoChange = e => {
const { name,value} = e.target;
setFormData({...formData
[e.target.name]: e.target.value,
})
}

Related

How to read and change big arr in React

I have a state that contains another array. I need to get this array to return it as a list. The new Item should appear as an object in the application array. I don't quite understand what I did wrong. How can I fix this?
** enter image description here
import React, { useState } from 'react'
function App() {
const [data, setData] = useState([
{
name: 'Ivan Pupkin',
email: 'ivan#gmail.com',
phone: '+34452344323',
application: [
{
nameOfApp: 'Name of App',
type: 'It and business',
description: 'some description',
},
],
},
])
const [name, setName] = useState('');
const [type, setType] = useState('');
const [description, setDescription] = useState('');
const addNewUser = (e) => {
e.preventDefault()
setData(current => current.map(item => [...item.application, {
personalId: 4,
nameOfApp: name,
description: description,
type: type
}]))
}
const Users = data.map(item => item.application.map((elem, index) => {
return(
<div key={index}>
<div>{elem.nameOfApp}</div>
<div>{elem.type}</div>
<div>{elem.description}</div>
</div>
)
}))
return (
<div>
<form action="#">
<input onChange={(e) => setName(e.target.value)} placeholder='name'/>
<input onChange={(e) => setType(e.target.value)} placeholder='type'/>
<input onChange={(e) => setDescription(e.target.value)} placeholder='desc'/>
<button onClick={addNewUser} type='submit'>submit</button>
</form>
<br />
<br />
<br />
{Users}
</div>
)
}
export default App
I'm not sure if I've understand what you're tring to do but here is a working version :
Basically, I just say which user I want to edit in addUser() then search it, assign new application to it, and return the array of users without the previous user
If I were you, I would avoid to have objects / array without ids :)
import React, { useState } from "react";
function App() {
const [data, setData] = useState([
{
id: 1,
name: "Ivan Pupkin",
email: "ivan#gmail.com",
phone: "+34452344323",
application: [
{
id: 1,
nameOfApp: "Name of App",
type: "It and business",
description: "some description"
}
]
}
]);
const [name, setName] = useState("");
const [type, setType] = useState("");
const [description, setDescription] = useState("");
const addNewUser = (e, targetUserId) => {
e.preventDefault();
setData((prevUsers) => {
const editedUser = prevUsers.find(({ id }) => id === targetUserId);
editedUser.application.push({
nameOfApp: name,
type: type,
description: description
});
const newUsers = [
...prevUsers.filter(({ id }) => id !== targetUserId),
editedUser
];
return newUsers;
});
};
const Users = data.map((item) =>
item.application.map((elem, index) => {
return (
<div key={index}>
<div>{elem.nameOfApp}</div>
<div>{elem.type}</div>
<div>{elem.description}</div>
</div>
);
})
);
return (
<div>
<form action="#">
<input onChange={(e) => setName(e.target.value)} placeholder="name" />
<input onChange={(e) => setType(e.target.value)} placeholder="type" />
<input
onChange={(e) => setDescription(e.target.value)}
placeholder="desc"
/>
<button onClick={(e) => addNewUser(e, 1)} type="submit">
submit
</button>
</form>
<br />
<br />
<br />
{Users}
</div>
);
}
export default App;
Hope it helped you !

how to clear all inputs in react div

import "./App.css";
import { useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { addUser} from "./features/Users";
function App() {
const dispatch = useDispatch();
const userList = useSelector((state) => state.users.value);
const [name, setName] = useState("");
const [username, setUsername] = useState("");
return (
<div className="App">
{" "}
<div className="addUser">
<input
type="text"
placeholder="Name..."
onChange={(event) => {
setName(event.target.value);
}}
/>
<input
type="text"
placeholder="Username..."
onChange={(event) => {
setUsername(event.target.value);
}}
/>
<button
onClick={() => {
dispatch(
addUser({
id: userList[userList.length - 1].id + 1,
name,
username,
})
);
}}
>
{" "}
Add User
</button>
</div>
);}
I am new to react and redux. After clicking the "Add User" button, new User data from inputs in the code will be added to the backend list. I want the values in input sections to be cleared after clicking the "Add User" button, but I don't know how to do.
you need to clear your state after click on submit button. for ex: set function like =>
const clearData = {
setName("")
setUsername("")
}
and pass the func to your onClick event.
onClick={clearData}
The following code will work perfectly fine.
Just assign value={name} and value={username} to both input types respectively and when you click Add User just clear the data in both the states.
import "./App.css";
import { useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { addUser} from "./features/Users";
function App() {
const dispatch = useDispatch();
const userList = useSelector((state) => state.users.value);
const [name, setName] = useState("");
const [username, setUsername] = useState("");
return (
<div className="App">
{" "}
<div className="addUser">
<input
type="text"
placeholder="Name..."
value={name}
onChange={(event) => {
setName(event.target.value);
}}
/>
<input
type="text"
placeholder="Username..."
value={username}
onChange={(event) => {
setUsername(event.target.value);
}}
/>
<button
onClick={() => {
setName("");
setUsername("");
dispatch(
addUser({
id: userList[userList.length - 1].id + 1,
name,
username,
})
);
}}
>
{" "}
Add User
</button>
</div>
);}
You can maintain a simple variable with list of form fields and can update the form state with the variable when you needed to clear form data. The below approach comes handy when you need to add additional fields as well.
import "./App.css";
import { useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { addUser} from "./features/Users";
const formFields = { name: '', username: '' };
function App() {
const dispatch = useDispatch();
const userList = useSelector((state) => state.users.value);
const [params, setParams] = useState(formFields)
const handleChange = (e) => {
const { name, value } = e.target;
setParams({ ...params }, ...{[name]: value});
}
const clearForm = () => setParams(formFields);
return (
<div className="App">
<div className="addUser">
<input
type="text"
placeholder="Name..."
value={params.name}
onChange={(e) => handleChange(e)}
/>
<input
type="text"
placeholder="Username..."
value={params.username}
onChange={(e) => handleChange(e)}
/>
<button
onClick={() => {
dispatch(
addUser({
id: userList[userList.length - 1].id + 1,
...params
})
);
clearForm();
}}
>
{" "}
Add User
</button>
</div>
</div>
)
}

Using regex with react hooks

I am basically trying to save the phone number entered by the user without braces, spaces or dashes but I somehow fail to do that. I am calling the regex after submitting the form in handleSubmit function through the setting of state and it prints out (and renders) without any change. Any idea what went wrong?
import React, { useContext, useState, useEffect } from "react";
import DataContext from "../store/data-context";
function Form() {
const [name, setName] = useState("");
const [secName, setSecName] = useState("");
const [tel, setTel] = useState("");
const [note, setNote] = useState("");
const [state, setState] = useState({
name: "",
secName: "",
tel: "",
note: "",
});
const { dispatchDataState } = useContext(DataContext);
const handleSubmit = (e) => {
e.preventDefault();
setTel((tel)=>tel.replace(/[^+\d]+/g, ""))
console.log(name);
dispatchDataState({ type: "ADD_DATA", payload: state });
setState(
{
name: "",
secName: "",
tel: "",
note: "",
}
)
console.log(state);
};
return (
<div>
<form onSubmit={handleSubmit}>
<label>
Jméno
<input
type="text"
required
value={state.name}
onChange={(e) => setState({ ... state, name: e.target.value })}
/>
</label>
<label>
Příjmení
<input
type="text"
required
value={state.secName}
onChange={(e) => setState({ ... state, secName: e.target.value })}
/>
</label>
<label>
Telefonní číslo
<input
type="text"
required
value={state.tel}
onChange={(e) => setState({ ... state, tel: e.target.value })}
/>
</label>
<label>
Poznámka
<input
type="text"
value={state.note}
onChange={(e) => setState({ ... state, note: e.target.value })}
/>
</label>
<input type="submit" value="Odeslat" />
</form>
</div>
);
}
export default Form;

How to show Inputs Values in Object in React

I try to show all data onChange inputs in Object to post it in API in React and I tried the following:
import React, { useState} from "react";
const Counter = () => {
const [form, setForm] = useState({});
const FormData = (event, {name, value}) => {
setForm({...form, [name]: value});
};
return (
<div>
<input value={form.username || ''} name="username" onChange={FormData} type="text"/>
<input value={form.email || ''} name="email" onChange={FormData} type="email"/>
<input value={form.password || ''} name="password" onChange={FormData} type="password"/>
</div>
);
}
export default Counter;
But it shows issue onChange : "Cannot destructure property 'name' of 'undefined' as it is undefined"
It can be done as follows:
const Counter = () => {
const [form, setForm] = useState({});
const FormData = (event) => {
const { target: { value, name } } = event;
setForm({...form, [name]: value});
};
return (
<div>
<input value={form.username || ''} name="username" onChange={FormData} type="text"/>
// same for other inputs
</div>
);
}

React Axios Input Undefined

I must post {input} data to http://localhost:4000/prediction with Axios. But {input} turns undefined.
I am using const instead of class Main extends component. onChange, it sets form data.
const Main = ({ value, suggestions, auth: { user } }) => {
const [formData, setFormData] = useState("");
const [messages, setMessages] = useState([]);
const { input } = formData;
const onChange = e => setFormData(e.target.value);
const onSubmit = event => {
event.preventDefault();
setMessages(prevMsgs => [...prevMsgs, formData]);
console.log({ input });
Axios post.
axios
.post(
`http://localhost:4000/prediction`,
{ input },
{ crossdomain: true }
)
.then(res => {
console.log(res.data);
//setMessages(prevMsgs => [...prevMsgs, formData]);
})
.catch(error => {
console.log(error.message);
});
};
Return (form) with onSubmit, onChange.
return (
<div className="true">
<br />
<form noValidate onSubmit={e => onSubmit(e)}>
<div className="input-group mb-3">
<input
name="input"
type="text"
className="form-control"
placeholder="Type text"
onChange={e => onChange(e)}
/>
)}
<div className="input-group-append">
<button className="btn btn-outline-secondary">Send</button>
</div>
</div>
</form>
</div>
);
};
As I have mentioned in the comment section formData is a string as I see which does not have a property called input what you try to destructure and that's why it is undefined always.
If you really need that format for axios then you can try change the structure of formData with useState as the following first:
const [formData, setFormData] = useState({input: null});
Then maybe you can try updating as:
const onChange = e => setFormData({input: e.target.value});
I hope that helps!

Categories