I want to pass the form data from the child component to the parent component I know it's easy to send the data using the event handler called onSubmit but I need this data to pass whenever the form gets change
So I tried to do it like this: PS - This isn't my original code this is the code I write for practice this situation
App.js [Parent Component]
import React from 'react';
import Form from './Form';
function App() {
function getData (data) {
console.log (`coming from the parent component ${data}`)
}
return (
<div className="App">
<Form onSubmit={getData}/>
</div>
);
}
export default App;
Form.js [child Component]
import React from 'react';
function Form(props) {
const [name, setName] = React.useState('');
const [answer, setAnswer] = React.useState('');
function handleChange(event) {
setName(event.target.value);
setAnswer(event.target.value);
props.onSubmit(answer);
}
console.log(answer);
return (
<>
<form>
<input type="text" value={name} onChange={handleChange} />
<br />
<input
onChange={handleChange}
type="radio"
value="Radio 1"
name="paka"
/>{'Radio 1'}
<input
onChange={handleChange}
type="radio"
value="Radio 2"
name="paka"
/>{'Radio 2'}
<input
onChange={handleChange}
type="radio"
value="Radio 3"
name="paka"
/>{'Radio 3'}
<input
onChange={handleChange}
type="radio"
value="Radio 4"
name="paka"
/>{'Radio 4'}
<br />
</form>
</>
);
}
export default Form;
so when I try to do it like this when I first press in radio child it's passes nothing. and when I press the another radio it's pass the previously pressed button
The reason why it's one step behind is that you're using trying to use the state you just set as the handler argument but since the operation to update the state is batched and asynchronous that state isn't immediately available. The easiest way to solve the problem outlined in this code is to send the event value as the handler argument: props.onSubmit(event.value)
.
The alternative would be to add a useEffect
hook to watch for changes in the answer state and then call the submit handler:
useEffect(() => props.onSubmit(answer), [answer]);
A couple of further points which my updated working example incorporates.
Since you have just input elements you don't necessarily need a form element to wrap them.
For better accessibility use labels for your inputs. Identify which label corresponds with what input by adding an htmlFor
attribute on the label, and an id
attribute on the input.
It would be easier (and probably more meaningful) to call your handler handleSubmit
to differentiate it from the element event handler called onSubmit
.
const { Fragment, useState } = React;
function App() {
function handleSubmit(data) {
console.log(`coming from the parent component ${data}`)
}
return (
<div className="App">
<Form handleSubmit={handleSubmit} />
</div>
);
}
function Form({ handleSubmit }) {
const [name, setName] = useState('');
const [answer, setAnswer] = useState('');
function handleChange(event) {
const { value } = event.target;
setName(value);
setAnswer(value);
handleSubmit(value);
}
return (
<Fragment>
<section className="name">
<label htmlFor="name">Name</label>
<input
id="name"
type="text"
value={name}
onChange={handleChange}
/>
</section>
<section className="radios">
<label htmlFor="radio1">Radio 1</label>
<input
id="radio1"
onChange={handleChange}
type="radio"
value="Radio 1"
name="paka"
/>
<label htmlFor="radio2">Radio 2</label>
<input
id="radio2"
onChange={handleChange}
type="radio"
value="Radio 2"
name="paka"
/>
<label htmlFor="radio3">Radio 3</label>
<input
id="radio3"
onChange={handleChange}
type="radio"
value="Radio 3"
name="paka"
/>
<label htmlFor="radio4">Radio 4</label>
<input
id="radio4"
onChange={handleChange}
type="radio"
value="Radio 4"
name="paka"
/>
</section>
</Fragment>
);
}
const node = document.getElementById('root');
const root = ReactDOM.createRoot(node);
root.render(<App />);
.name label { margin-right: 0.25em; }
.radios label:not(:first-child) { margin-left: 0.5rem; }
.radios { margin-top: 1em; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.min.js"></script>
<div id="root"></div>