英文:
How to pass a form (Radio Button) data from child to parent onChange in REACT
问题
以下是您要翻译的部分:
"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
This following image will be a example"
英文:
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
答案1
得分: 1
原因是你试图将刚设置的状态用作处理程序参数,但由于更新状态的操作是批处理和异步的,因此该状态不会立即可用。解决此代码中概述的问题的最简单方法是将事件值作为处理程序参数发送:props.onSubmit(event.value)
。
另一种方法是添加一个useEffect
钩子来监视答案状态的变化,然后调用提交处理程序:
useEffect(() => props.onSubmit(answer), [answer]);
我更新的示例中还包括几点进一步说明:
-
由于您只有输入元素,不一定需要用
form
元素包装它们。 -
为了更好的可访问性,使用标签为您的输入添加标签。通过在标签上添加
htmlFor
属性和输入上添加id
属性来确定哪个标签对应于哪个输入。 -
将处理程序命名为
handleSubmit
可能更容易(而且可能更有意义),以区别于元素事件处理程序onSubmit
。
function handleSubmit(data) {
console.log(`来自父组件的消息 ${data}`)
}
<label htmlFor="name">姓名</label>
<input
id="name"
type="text"
value={name}
onChange={handleChange}
/>
.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>
英文:
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 anid
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 calledonSubmit
.
<!-- begin snippet: js hide: false console: true babel: true -->
<!-- language: lang-js -->
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 />);
<!-- language: lang-css -->
.name label { margin-right: 0.25em; }
.radios label:not(:first-child) { margin-left: 0.5rem; }
.radios { margin-top: 1em; }
<!-- language: lang-html -->
<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>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论