如何在React中通过onChange将表单(单选按钮)数据从子组件传递到父组件

huangapple go评论55阅读模式
英文:

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 &#39;react&#39;;
import Form from &#39;./Form&#39;;

function App() {

  function getData (data) {
      console.log (`coming from the parent component ${data}`)
  }

  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;Form onSubmit={getData}/&gt;
    &lt;/div&gt;
  );
}

export default App;

Form.js [child Component]

import React from &#39;react&#39;;

function Form(props) {
  const [name, setName] = React.useState(&#39;&#39;);
  const [answer, setAnswer] = React.useState(&#39;&#39;);

  function handleChange(event) {
    setName(event.target.value);
    setAnswer(event.target.value);
    props.onSubmit(answer);
  }

  console.log(answer);

  return (
    &lt;&gt;
      &lt;form&gt;
        &lt;input type=&quot;text&quot; value={name} onChange={handleChange} /&gt;
        &lt;br /&gt;
        &lt;input
          onChange={handleChange}
          type=&quot;radio&quot;
          value=&quot;Radio 1&quot;
          name=&quot;paka&quot;
        /&gt;{&#39;Radio 1&#39;}
        &lt;input
          onChange={handleChange}
          type=&quot;radio&quot;
          value=&quot;Radio 2&quot;
          name=&quot;paka&quot;
        /&gt;{&#39;Radio 2&#39;}
        
        &lt;input
          onChange={handleChange}
          type=&quot;radio&quot;
          value=&quot;Radio 3&quot;
          name=&quot;paka&quot;
        /&gt;{&#39;Radio 3&#39;}
        
        &lt;input
          onChange={handleChange}
          type=&quot;radio&quot;
          value=&quot;Radio 4&quot;
          name=&quot;paka&quot;
        /&gt;{&#39;Radio 4&#39;}
        
        &lt;br /&gt;
      &lt;/form&gt;
    &lt;/&gt;
  );
}

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

答案1

得分: 1

原因是你试图将刚设置的状态用作处理程序参数,但由于更新状态的操作是批处理和异步的,因此该状态不会立即可用。解决此代码中概述的问题的最简单方法是将事件值作为处理程序参数发送:props.onSubmit(event.value)

另一种方法是添加一个useEffect钩子来监视答案状态的变化,然后调用提交处理程序:

useEffect(() => props.onSubmit(answer), [answer]);

我更新的示例中还包括几点进一步说明:

  1. 由于您只有输入元素,不一定需要用form元素包装它们。

  2. 为了更好的可访问性,使用标签为您的输入添加标签。通过在标签上添加htmlFor属性和输入上添加id属性来确定哪个标签对应于哪个输入。

  3. 将处理程序命名为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(() =&gt; props.onSubmit(answer), [answer]);

A couple of further points which my updated working example incorporates.

  1. Since you have just input elements you don't necessarily need a form element to wrap them.

  2. 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.

  3. It would be easier (and probably more meaningful) to call your handler handleSubmit to differentiate it from the element event handler called onSubmit.

<!-- 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 (
    &lt;div className=&quot;App&quot;&gt;
      &lt;Form handleSubmit={handleSubmit} /&gt;
    &lt;/div&gt;
  );
}

function Form({ handleSubmit }) {
  
  const [name, setName] = useState(&#39;&#39;);
  const [answer, setAnswer] = useState(&#39;&#39;);

  function handleChange(event) {
    const { value } = event.target;
    setName(value);
    setAnswer(value);
    handleSubmit(value);
  }

  return (
    &lt;Fragment&gt;
      &lt;section className=&quot;name&quot;&gt;
        &lt;label htmlFor=&quot;name&quot;&gt;Name&lt;/label&gt;
        &lt;input
          id=&quot;name&quot;
          type=&quot;text&quot;
          value={name}
          onChange={handleChange}
        /&gt;
      &lt;/section&gt;
      &lt;section className=&quot;radios&quot;&gt;
        &lt;label htmlFor=&quot;radio1&quot;&gt;Radio 1&lt;/label&gt;
        &lt;input
          id=&quot;radio1&quot;
          onChange={handleChange}
          type=&quot;radio&quot;
          value=&quot;Radio 1&quot;
          name=&quot;paka&quot;
        /&gt;
        &lt;label htmlFor=&quot;radio2&quot;&gt;Radio 2&lt;/label&gt;
        &lt;input
          id=&quot;radio2&quot;
          onChange={handleChange}
          type=&quot;radio&quot;
          value=&quot;Radio 2&quot;
          name=&quot;paka&quot;
        /&gt;
        &lt;label htmlFor=&quot;radio3&quot;&gt;Radio 3&lt;/label&gt;
        &lt;input
          id=&quot;radio3&quot;
          onChange={handleChange}
          type=&quot;radio&quot;
          value=&quot;Radio 3&quot;
          name=&quot;paka&quot;
        /&gt;
        &lt;label htmlFor=&quot;radio4&quot;&gt;Radio 4&lt;/label&gt;
        &lt;input
          id=&quot;radio4&quot;
          onChange={handleChange}
          type=&quot;radio&quot;
          value=&quot;Radio 4&quot;
          name=&quot;paka&quot;
        /&gt;
      &lt;/section&gt;
    &lt;/Fragment&gt;
  );

}


const node = document.getElementById(&#39;root&#39;);
const root = ReactDOM.createRoot(node);
root.render(&lt;App /&gt;);

<!-- 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 -->

&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.min.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.min.js&quot;&gt;&lt;/script&gt;
&lt;div id=&quot;root&quot;&gt;&lt;/div&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年5月14日 09:51:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/76245508.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定