I am creating a react app which is using local storage. I am saving and array of objects to local storage.
when I try to save to local storage the data is saving.
and then when I refresh the page the saved data is becoming empty object,
like this [].
if any one knows why its happening please help me
import React, {useEffect, useState} from 'react';
import Addcontact from './Addcontact';
import './App.css';
import Contactlist from './Contactlist';
import { Header } from './Header';
function App() {
const keyy ="contactlist"
const [contacts, setcontacts] = useState([])
const contactshandler = (contact)=> {
console.log(contact)
setcontacts([...contacts, contact])
}
useEffect(() => {
const getdata = JSON.parse(localStorage.getItem(keyy))
getdata && setcontacts(getdata)
}, [])
useEffect(() => {
localStorage.setItem(keyy, JSON.stringify(contacts));
}, [contacts])
return (
<div className="ui container">
<Header />
<Addcontact contacts={contacts} contactshandler={contactshandler} />
<Contactlist contacts={contacts} />
</div>
);
}
app component
import React, { useState } from 'react'
function Addcontact({contacts, setcontacts, contactshandler}) {
const [user, setuser] = useState({username:'', email:''})
const addvalue = (e) => {
e.preventDefault();
console.log(user)
contactshandler(user)
setuser({username:'', email:''})
}
return (
<div>
<div className='ui main'>
<h2> Add Contact</h2>
<form className='ui form' onSubmit={addvalue}>
<div className=''>
<label>name</label>
<input name="name" placeholder='name' value={user.username} onChange={(e) => setuser({...user, username : e.target.value })} />
</div>
<div className='feild'>
<label>email</label>
<input email='email' placeholder='email' value={user.email} onChange={(e) => setuser({...user, email: e.target.value})} />
</div>
<button>add</button>
</form>
</div>
</div>
)
}
export default Addcontact
export default App;
add component
this is the value showing when saving after refresh this value becomes empty object
enter image description here
console
enter image description here
You don't need useEffect to read the data. You can initially read it.
const [contacts, setcontacts] = useState(JSON.parse(localStorage.getItem(keyy)) ?? [])
and remove
useEffect(() => {
const getdata = JSON.parse(localStorage.getItem(keyy))
getdata && setcontacts(getdata)
}, [])
I am trying to create a form to add a new item into an array, but I am getting the error: Form submission cancelled because form is not connected. I found some posts saying that replacing the submit button type with "button" instead of "submit" but its not working.
My code is below:
import React, { useState,useContext } from 'react';
import { ItemContext } from "../ItemsContext.js";
const AddExpense = ( )=> {
const [items,setItems] = useContext(ItemContext)
const [name,setName] = useState()
const [price,setPrice] = useState()
const handleSubmit = ()=>{
const newItem = {title:name,price:price}
const newList = items.budgetItems.pop(newItem)
setItems({budget:items.budget, budgetItems:newList})
}
const handleNameChange=(event)=>{
setName(event.target.value)
}
const handlePriceChange= (event)=>{
setPrice(event.target.value)
}
return (
<div onSubmit={handleSubmit}>
<form >
<label htmlFor="name">Name</label>
<input type="text" id="name" onChange={handleNameChange} />
<label htmlFor="price">Price</label>
<input type="number" id="price" onChange={handlePriceChange}/>
<input type="submit" value="Add"/>
</form>
</div>
)
}
export default AddExpense
Display expenses code:
import React, { useContext } from 'react';
import Expense from './expenses.js'
import { ItemContext } from "../ItemsContext.js";
const ExpenseDisplay =()=> {
const [items, setItems] = useContext(ItemContext)
let stuff = items.budgetItems
return (
<div>
{stuff.map((items)=><Expense key={items.id} items={items}/>)}
</div>
)
}
export default ExpenseDisplay;
Expense Component:
import React, { useContext,useState} from 'react';
import { ItemContext } from "../ItemsContext.js";
const Expense =({items})=> {
const [expense, setExpense] = useContext(ItemContext)
let stuff = expense.budgetItems
const handleRemove =()=> {
const newExpense = stuff.filter(itemChecked=>itemChecked.id!==items.id)
setExpense({budget:expense.budget, budgetItems:newExpense});
}
return (
<div className="expense">
<h3>{items.title}</h3>
<h3>{items.price}</h3>
<button onClick={handleRemove}>X</button>
</div>
)
}
export default Expense;
Edit: One answer suggested to move the onSubmit into the form element, but that did not work.
Add onSubmit to the form element
Change this
return (
<div onSubmit={handleSubmit}>
<form >
...
...
</form>
</div>
)
to
return (
<div>
<form onSubmit={handleSubmit}>
...
...
</form>
</div>
)
Error says that stuff is undefined It is better to check if stuff is not empty then map through it.
import React, { useContext } from 'react';
import Expense from './expenses.js'
import { ItemContext } from "../ItemsContext.js";
const ExpenseDisplay =()=> {
const [items, setItems] = useContext(ItemContext)
let stuff = items.budgetItems
if(stuff && stuff.length > 0){
return (
<div>
{stuff.map((items)=><Expense key={items.id} items={items}/>)}
</div>
)
}else{
return (
<p>There is no item in stuff.</p>
)
}
}
export default ExpenseDisplay;
So my App.js file looks like this:
import React from "react";
import { useState } from "react";
import './App.css';
import Header from "./components/pages/Header";
import NAV from "./NAV";
import Trees from "./components/tree";
function App() {
const [inputField , setInputField] = useState({
first_name: 'Phyag_NZFS3770'
})
const inputsHandler = (e) =>{
setInputField( {[e.target.name]: e.target.value} )
}
const submitButton = () =>{
alert(inputField.first_name)
}
return(
<div className="App">
<NAV genomename={inputField.first_name}/> //this can't be done as the prop value is undefined
<Header title="EumicrobeDB"/>
<h3 style={{ textAlign:"left" }}> Organism List </h3>
<div> <Trees /> </div>
<div>
<input
type="text"
name="first_name"
onChange={inputsHandler}
placeholder="enter the organism id"
value={inputField.first_name}/>
<button onClick={submitButton}>Submit Now</button>
</div>
</div>
)
}
export default App;
Can anyone please modify the code to pass {inputField.first_name} as prop value to my function called NAV? I am in an absolute fix..I am a biologist who is new to React; who has to meet a deadline
This is how you can pass data from parent component to child as a props.
Example
import React from "react";
import { useState } from "react";
const Header = ({ title }) => {
return <React.Fragment>Hello, {title}</React.Fragment>;
};
function App() {
const [inputField, setInputField] = useState({
first_name: "Phyag_NZFS3770"
});
const inputsHandler = (e) => {
console.log([e.target.name] , e.target.value);
setInputField({ [e.target.name]: e.target.value });
};
const submitButton = () => {
alert(inputField.first_name);
};
return (
<div className="App">
<Header title={inputField.first_name} />
<h3 style={{ textAlign: "left" }}> Organism List </h3>
<div>
<input
type="text"
name="first_name"
onChange={inputsHandler}
placeholder="enter the organism id"
value={inputField.first_name}
/>
<button onClick={submitButton}>Submit Now</button>
</div>
</div>
);
}
export default App;
Your code in this component looks fine as-is. Make sure you're accessing props.genomename and not props.first_name in the NAV component.
If you're planning to add more input fields, I'd also suggest you change the inputHandler function to merge with the previous state, rather than replacing it entirely:
const inputsHandler = (e) => {
setInputField({ ...inputField, [e.target.name]: e.target.value })
}
I have custom component which I am importing in my another Component as a Element tag. My custom Component consist of dropdown values. I want to read value the value of in my element tag when I submit my form
custom component :
import React, { useState, useMemo } from 'react'
import Select from 'react-select'
import countryList from 'react-select-country-list'
function CountrySelector() {
const [value, setValue] = useState('')
const options = useMemo(() => countryList().getData(), [])
const changeHandler = value => {
setValue(value)
}
return <Select options={options} value={value} onChange={changeHandler} />
}
export default CountrySelector
i want to use that custom component country selector values on my submit button:
main component:
import react from 'react';
import CountrySelector from '../../helpers/CountrySelector';
import IdType from '../../helpers/IdType';
import ProofOfAddress from '../../helpers/ProofOfAddress';
const submitForm=(e)=>{
//debugger;
e.preventDefault();
console.warn(e.target)
};
const IdentityVerification = (props) => {
const saveUser=(e)=>{
console.warn({e});
}
return (
<form onSubmit={submitForm} >
<div className='app'>
<label >Choose Issuing Country/region</label>
<CountrySelector/>
<label >Select ID Type</label>
<IdType/>
<label >Proof of Address</label>
<ProofOfAddress/>
</div>
<div className="form-actions">
<button >Submit</button>
</div>
</form>
);
};
export default IdentityVerification;
how can i read values?
The normal way to handle this would be to move the state and your changeHandler function into the parent component and pass the handler down to the child as a prop.
const IdentityVerification = (props) => {
const [value, setValue] = useState('')
const changeHandler = value => {
setValue(value)
}
return (
// ...
<CountrySelector onChange={changeHandler}/>
// ...
);
and in your child:
function CountrySelector({changeHandler}) {
// ....
return <Select options={options} value={value} onChange={changeHandler} />
}
Could you please tell me how to get input field value on button click in react , I am using react hooks .I want to get first name and lastname value on button click. I already pass name attribute in my function component.
Here is my code
import React, { Component, useState } from 'react';
import { render } from 'react-dom';
export default function InputField({name,label}) {
const [state, setState] = useState('')
return (
<div>
<label>{label}</label>
<input type="text"
value={state}
name={name}
onChange={(e) => setState(e.target.value)} />
{state}
</div>
);
}
Use <form> tag with useRef hook
Wrap your <InputField> tags with an html <form> tag and put a react ref on the later. Like this:
import React, { Component, useRef } from 'react'
import { render } from 'react-dom'
import InputField from './inputfield'
import './style.css'
function App () {
const nameForm = useRef(null)
const handleClickEvent = () => {
const form = nameForm.current
alert(`${form['firstname'].value} ${form['lastname'].value}`)
}
return (
<div>
<form ref={nameForm}>
<InputField label={'first name'} name={'firstname'}/>
<InputField label={'last name'} name={'lastname'}/>
</form>
<button onClick={handleClickEvent}>gett value</button>
</div>
)
}
render(<App />, document.getElementById('root'))
Working example: https://stackblitz.com/edit/react-shtnxj
The Easiest Way For Me is useRef
With useRef it's pretty simple. Just add ref name and then submit.
const email = useRef(null);
function submitForm(e){
e.preventDefault();
console.log(email.current.value);
}
return (
<div>
<form onSubmit={submitForm}>
<input type="text" ref={email} />
<button>Submit</button>
</form>
</div>
)
You could always lift up the state in parent component.
codeSandbox link
Parent Component
import React from "react";
import ReactDOM from "react-dom";
import ChildComponent from "./Child";
const { useState } = React;
function App() {
const [first_name, setFirstName] = useState("");
const [last_name, setLastName] = useState("");
const handleFirstNameChange = ({ target }) => {
setFirstName(target.value);
};
const handleLastNameChange = ({ target }) => {
setLastName(target.value);
};
const handleClick = () => {
console.log(first_name);
console.log(last_name);
};
return (
<div className="App">
<ChildComponent
label="first name"
onChange={handleFirstNameChange}
value={first_name}
/>
<ChildComponent
label="last name"
onChange={handleLastNameChange}
value={last_name}
/>
<button onClick={handleClick}>Click me</button>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Child Component
import React from "react";
const ChildComponent = ({ label, onChange, value, name }) => {
return (
<div>
<label>{label}</label>
<input type="text" value={value} name={name} onChange={onChange} />
</div>
);
};
export default ChildComponent;
You could always combine onChange handler for first name and last name.
Hope that helps!!!
A good solution is to move the state from InputField component into index:
const [F_name, setF_name] = useState('')
const [L_name, setL_name] = useState('')
now you should pass state value and event handler to InputField to change the state when input is changed:
<InputField label={'first name'} name={'firstname'} value={F_name} changed={(name) => setF_name(name)}/>
In Your InputField field: edit it to be like:
<input type="text"
value={value}
name={name}
onChange={(e) => changed(e.target.value)} />
See Working Demo Here
import React, { useRef } from 'react'
const ViewDetail = () => {
const textFirstName = useRef(null)
const onChange = e => {
console.log(textFirstName.current.state.value)
}
return <Input maxLength={30} ref={textFirstName} placeholder="Nombre" onChange=onChange} />
}
I can think of these approaches -
You can pull the state up to the parent component.
App.js
const [user, setUser] = useState('');
return (
<Inputfield setValue={setUser} value={user} />
);
InputField.js
<input value={props.value} onChange={(e) => setValue(e.target.value)} />
You can use ref to access indiviual element value.
If you have data distributed across multiple components you can also make use of Context API
Hope this helps!
Do let me know if you need more info on any of the option. Thanks!
You should do the react hooks work on your index and pass the value and the onChange function to your InputField component.
//index page
import React, { Component, useState } from 'react';
import { render } from 'react-dom';
import InputField from './inputfield';
import './style.css';
function App() {
const [firstname, setFirstName] = useState('');
const [lastname, setLastName] = useState('');
const handleClickEvent = ()=>{
setFirstName('Will');
setLastName('smith');
}
return (
<div>
<InputField
label={'first name'}
name={'firstname'}
value={firstname}
onChange={setFirstName}
/>
<InputField
label={'last name'}
name={'lastname'}
value={lastname}
onChange={setLastName}
/>
<button
onClick={handleClickEvent}
>Get value</button>
</div>
);
}
render(<App />, document.getElementById('root'));
// input field
import React, { Component, useState } from 'react';
import { render } from 'react-dom';
export default function InputField({name,label, value, onChange}) {
return (
<div>
<label>{label}</label>
<input type="text"
value={value}
name={name}
onChange={(e) => onChange(e.target.value)} />
{value}
</div>
);
}
While keeping the majority of your structure the same, I think the simplest and most React solution is to use forwardRef() which in a nut-shell let's us communicate between then parent-component and child-components.
See working sandbox.
App.js
import React, { useRef } from "react";
import InputField from "./InputField";
import ReactDOM from "react-dom";
function App() {
const handleClickEvent = () => {
if (firstName.current && lastName.current) {
console.log(`firstName: ${firstName.current.value}`);
console.log(`lastName: ${lastName.current.value}`);
}
};
const firstName = useRef(null);
const lastName = useRef(null);
return (
<div>
<InputField ref={firstName} label={"first name"} name={"firstname"} />
<InputField ref={lastName} label={"last name"} name={"lastname"} />
<button onClick={handleClickEvent}>Get value</button>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
InputField.js
import React, { useState } from "react";
const InputField = React.forwardRef((props, ref) => {
const [state, setState] = useState("");
return (
<div>
<label>{props.label}</label>
<input
ref={ref}
type="text"
value={state}
name={props.name}
onChange={e => setState(e.target.value)}
/>
{state}
</div>
);
});
export default InputField;
Notice that with this structure, you are not required to pass in any state updating function as props to the InputField component. The value that you enter into each input will be strictly maintained by the individual component. It is independent from the Parent, and therefore makes it much more reusable.
The refs we created allow us to tap into specific elements of the InputField so we extract the desired values. In this case, we can get first-name and last-name through the handleClickEvent function.
you can achieve this doing the following:
import React, { Component, useState } from 'react';
import { render } from 'react-dom';
export default function InputField({name,label}) {
const [state, setState] = useState('');
const handleChange = e => {
setState(e.target.value);
};
return (
<div>
<label>{label}</label>
<input
type="text"
value={state}
name={name}
onChange={handleChange}
/>
{state}
</div>
);
}
Hopes this helps.
well one simple(but not necessarily recommended) way is to provide an id or a ref like this in index.js
<InputField label={'first name'} name={'firstname'} id={"ip1"}/>
<InputField label={'last name'} name={'lastname'} id={"ip2"}/>
and in your inputfield.js pass the id props to the input fields like this
<input type="text"
value={state}
name={name}
onChange={(e) => setState(e.target.value)}
id= {id}/>
Now you can call them in the onClick of the button like this in index.js
const handleClickEvent = ()=>{
alert(document.getElementById("ip1").value);
}
The second, more preferable way is to set the state variable in index.js
function App() {
const [stateIp1, setStateIp1] = useState('');
const [stateIp2, setStateIp2] = useState('');
const handleClickEvent = ()=>{
alert(stateIp1);
}
return (
<div>
<InputField label={'first name'} state={stateIp1} setState={setStateIp1} name={'firstname'} id={"ip1"}/>
<InputField label={'last name'}state={stateIp2} setState={setStateIp2} name={'lastname'} id={"ip2"}/>
<button
onClick={handleClickEvent}
>Get value</button>
</div>
);
}
Now your inputfield.js becomes
export default function InputField({name,label,id,setState,state}) {
return (
<div>
<label>{label}</label>
<input type="text"
value={state}
name={name}
onChange={(e) => setState(e.target.value)} id= {id}/>
</div>
);