简体   繁体   English

在一个组件中使用多个单选按钮组更新 state

[英]Updating state with multiple radio button groups in one component react

I am trying to update my component's state with the radio buttons' values.我正在尝试使用单选按钮的值更新我的组件的 state。 When I make the second radio button selection (reason for status) I get an error telling me当我进行第二个单选按钮选择(状态原因)时,我收到一条错误消息告诉我

Uncaught TypeError: cannot read properties of undefined (reading 'map')

When I click the submit button, the state is only showing the state for the first group of radio buttons ie current status and then it is showing the selected value as an empty string (default state value) and not the value as per the radio button selection当我单击提交按钮时,state 仅显示第一组单选按钮的 state 即当前状态,然后将所选值显示为空字符串(默认 Z9ED39E2EA931586B6A985A6942EF57 的值而不是按钮值)选择

Can anyone help?任何人都可以帮忙吗? Here is my code:这是我的代码:

import {Container, Row, Col, Form,  Button } from 'react-bootstrap';
import { useState } from 'react';



const Question = (q) => {

    //state to hold responses from input
    const [questionState, setQuestionState] = useState({
        options: [
            {   radioName: 'currentstatus',
                selected: '' },
            {   radioName: 'reasonstatus',
                selected: ''},
            {   radioName: 'actions',
                selected: ''},
            {   radioName: 'actowner',
                selected: ''},
            {   radioName: 'actstat',
                selected: ''}

        ]
    });

    //EVENT HANDLERS

    //radio buttons onchange
    const handleChange = (e)=>{
        const { options } = questionState;
        const {name, value} = e.target;
        console.log(name, value);
        
        const nextState = options.map( opt => {
            if (opt.radioName !== name) {
                return {...opt}
            } else {
                return {...opt, 
                    selected: value} 
            } 
        });

        setQuestionState(...options, {nextState});
        
    }

    //date picker event
    const handleDate = (e) => {
        console.log(e.target.value);

    }
    //overall form submission
    const handleSubmit = (e) => {
        console.log(questionState);
    }

    const question = q;
    return(

        <Container>
            <div className="question mb-5">
                <Form className="border border-3 border-primary p-3 m-2">
                    <Form.Group className="mb-2">
                        <Row className="bg-primary text-white p-2">
                            <div className="fs-5">{question.question}</div>
                        </Row>

                        {/* ---------------- CURRENT STATUS  ----------------------- */}
                        <Form.Label className="fs-4 fw-bold">Current Status:</Form.Label>
                            <div key="currStat" className="mb-3">
                                
                                <Form.Check inline label="Fully meeting expectation" name="currentstatus" type="radio" id='status-1' value="1" onChange={handleChange}/>
                                <Form.Check inline label="Partially meeting expectation" name="currentstatus" type="radio" id='status-2' value="2" onChange={handleChange}/>
                                <Form.Check inline label="Not meeting expectation" name="currentstatus" type="radio" id='status-3' value="3" onChange={handleChange}/>
                                <Form.Check inline label="Not applicable" name="currentstatus" type="radio" id='status-4' value="4" onChange={handleChange}/>
                            </div>
                                        

                        {/* -------------------- REASONS FOR STATUS --------------------------- */}
                        <Form.Label className="fs-4 fw-bold">Reason for Status:</Form.Label>
                            <div key="reasStat" className="mb-3">
                                <Form.Check inline label="Reason 1" name="reasonstatus" type="radio" id='reason-1' value="1" onChange={handleChange}/>
                                <Form.Check inline label="Reason 2" name="reasonstatus" type="radio" id='reason-2' value="2" onChange={handleChange}/>
                                <Form.Check inline label="Reason 3" name="reasonstatus" type="radio" id='reason-3' value="3" onChange={handleChange}/>
                                <Form.Check inline label="Reason 4" name="reasonstatus" type="radio" id='reason-4' value="4" onChange={handleChange}/>
                            </div>
                                        

                        {/* -------------------- ACTIONS --------------------------- */}
                        <Form.Label className="fs-4 fw-bold">Action to be taken:</Form.Label>
                            <div key="actions" className="mb-3">
                            <Form.Check inline label="Action 1" name="actions" type="radio" id='act-1' value="1" onChange={handleChange}/>
                            <Form.Check inline label="Action 2" name="actions" type="radio" id='act-2' value="2" onChange={handleChange}/>
                            <Form.Check inline label="Action 3" name="actions" type="radio" id='act-3' value="3" onChange={handleChange}/>
                            <Form.Check inline label="Action 4" name="actions" type="radio" id='act-4' value="4" onChange={handleChange}/>
                            </div>
                                       

                        {/* -------------------- ACTION OWNER --------------------------- */}
                        <Form.Label className="fs-4 fw-bold">Action Owner:</Form.Label>
                            <div key="actOwner" className="mb-3">
                            <Form.Check inline label="User 1" name="actowner" type="radio" id='user-1' value="1" onChange={handleChange}/>
                            <Form.Check inline label="User 2" name="actowner" type="radio" id='user-2' value="2" onChange={handleChange}/>
                            </div>
                        

                        {/* -------------------- ACTION STATUS --------------------------- */}
                        <Form.Label className="fs-4 fw-bold">Action Status:</Form.Label>
                            <div key="actStat" className="mb-3">
                            <Form.Check inline label="Not started" name="actstat" type="radio"id='actStat-1' value="1" onChange={handleChange}/>
                            <Form.Check inline label="In progress" name="actstat" type="radio" id='actStat-2' value="2" onChange={handleChange}/>
                            <Form.Check inline label="Completed" name="actstat" type="radio" id='actStat-3' value="3" onChange={handleChange}/>
                            </div>
                                       
                        {/*  --------------------- DATE PICKER ------------------------- */}
                        <Row>
                            <Col xs={4}>
                                <Form.Label className="fs-4 fw-bold">Due Date:</Form.Label>
                                <Form.Control xs={4} type="date" className="mb-3" onChange={handleDate}/>
                            </Col>
                        </Row>
                        <Row className="justify-content-end">
                            <Col xs={2}>
                        <Button onClick = {handleSubmit}>Submit</Button>
                        </Col>
                        </Row>
                    </Form.Group>
                </Form>
                                
            </div>
        </Container>
    )
}

export default Question;

In handleChange , the following is not a valid state update.handleChange中,以下不是有效的 state 更新。 Due to that, your state was missing options entry after each radio button click.因此,您的 state 在每次单击单选按钮后都缺少options条目。

setQuestionState(...options, {nextState});

1st way第一种方式

The above line should be replaced with the following.上述行应替换为以下行。

setQuestionState({ ...questionState, options: nextState });

编辑适度-ramanujan-mj25i

2nd way第二种方式

It is always safe to use the callback version of updating the state.使用更新 state 的回调版本始终是安全的。 Therefore, handleChange function should be corrected as below.因此, handleChange function 应如下更正。

  const handleChange = (e) => {
    const { name, value } = e.target;
    setQuestionState((prevState) => {
      return {
        ...prevState,
        options: prevState.options.map((opt) => {
          if (opt.radioName !== name) {
            return { ...opt };
          } else {
            return { ...opt, selected: value };
          }
        })
      };
    });
  };

编辑胡思乱想的cohen-cjseb

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM