rskybsn
rskybsn

Reputation: 87

Radio Buttons in React using Bootstrap always post same value

I am not getting an error, but the radio buttons I am writing are always sending the same value to the database, and I am not sure why or how to fix it.

UPDATE. I have attached the complete code. Hopefully this provides more detail. Everything is working but the radio buttons. Can someone shed some light as to how I can fix this?

import React from "react";
import axios from "axios";
import Form from 'react-bootstrap/Form'
import Row from 'react-bootstrap/Col'
import Button from 'react-bootstrap/Button'
import './Form.css'
class Home extends React.Component {
    constructor(props) {
        super(props);
        this.state = { tickets: [] };
        this.firstName = React.createRef();
        this.lastName = React.createRef();
        this.email = React.createRef();
        this.category = React.createRef();
        this.content = React.createRef();
        this.urgency = React.createRef();
    }

    componentDidMount() {
        this.getData();
    }

    getData = () => {
        // Java Spring Boot uses port 8080
        let url = "http://localhost:8080/tickets";
        // axios.get(url).then(response => console.log(response.data));
        axios.get(url).then(response => this.setState({ tickets: response.data }));
    };

    addTicket = () => {
        let url = "http://localhost:8080/tickets";
        axios.post(url, {
            firstName: this.firstName.current.value,
            lastName: this.lastName.current.value,
            email: this.email.current.value,
            category: this.category.current.value,
            content: this.content.current.value,
            urgency: this.urgency.current.value

        }).then(response => {
            // refresh the data
            this.getData();
            // empty the input
            this.firstName.current.value = "";
            this.lastName.current.value = "";
            this.email.current.value = "";
            this.content.current.value = "";
        });
    };


    render() {
        return (
            <div>
                <form onSubmit={this.handleSubmit}>
                    <Form.Group className="Input">
                        <Form.Control type="text" name="firstName" placeholder="First Name" ref={this.firstName} />
                    </Form.Group>
                    <Form.Group className="Input">
                        <Form.Control type="text" name="lastName" placeholder="Last Name" ref={this.lastName} />
                    </Form.Group>
                    <Form.Group className="Input">
                        <Form.Control type="text" name="email" placeholder="Email" ref={this.email} />
                    </Form.Group>
                    <br></br>

                    <Form.Group className="dropdown">
                        <Form.Label>Select a Category:</Form.Label>
                        <Form.Control as="select" ref={this.category}>
                            <option value="hardware">Hardware</option>
                            <option value="software">Software</option>
                            <option value="internet">Internet</option>
                            <option value="other">Other</option>
                        </Form.Control>
                    </Form.Group>
                    <br></br>

                    <Form.Group className="Issue">
                        <Form.Label>Please Describe Your Issue:</Form.Label>
                        <Form.Control as="textarea" rows="7" ref={this.content} />
                    </Form.Group>

                    <fieldset>
                        <Form.Group as={Row}>
                            <Form.Label className="radio" column sm={12}>
                                Select the Urgency Level:<br></br>
                            </Form.Label>
                            <Form.Check className="radioButtons"
                                type="radio"
                                label="Urgent"
                                name="selectedOption"
                                value="Urgent"
                                ref={this.urgency}
                            />
                            <Form.Check className="radioButtons"
                                type="radio"
                                label="Standard"
                                name="selectedOption"
                                value="Standard"
                                ref={this.urgency}
                            />
                            <Form.Check className="radioButtons"
                                type="radio"
                                label="Low Priority"
                                name="selectedOption"
                                value="Low Priority"
                                ref={this.urgency}
                            />
                        </Form.Group>
                    </fieldset>

                    <Button variant="secondary" type="button" className="submit" onClick={this.addTicket}>Submit Ticket</Button>
                </form>
            </div>
        );
    }
}

export default Home;

Upvotes: 1

Views: 551

Answers (2)

Robert
Robert

Reputation: 2763

you ref three elements to the same ref. you can walk around this without changing your login and adding state by helper function. in that way you don't change behavoir of your code (is not perferct ...) but you avoid rendering forced by setState.

import React from "react"

import Form from 'react-bootstrap/Form'
import Row from 'react-bootstrap/Col'
import Button from 'react-bootstrap/Button'

class Home extends React.Component {
  constructor(props) {
      super(props);
      this.state = { tickets: [] };
      this.firstName = React.createRef();
      this.lastName = React.createRef();
      this.email = React.createRef();
      this.category = React.createRef();
      this.content = React.createRef();
      this.urgency = React.createRef();
  }

  componentDidMount() {

  }

  getData = () => {

  };

  addTicket = () => {
      console.log({
          firstName: this.firstName.current.value,
          lastName: this.lastName.current.value,
          email: this.email.current.value,
          category: this.category.current.value,
          content: this.content.current.value,
          urgency: this.urgency.current.value

      })
  };

  handleCheckBoxChange(ref, event){
    if(event.target.checked){
      ref.current = {value: event.target.value}
    }
  }

  render() {
      return (
          <div>
              <form onSubmit={this.addTicket}>
                  <Form.Group className="Input">
                      <Form.Control type="text" name="firstName" placeholder="First Name" ref={this.firstName} />
                  </Form.Group>
                  <Form.Group className="Input">
                      <Form.Control type="text" name="lastName" placeholder="Last Name" ref={this.lastName} />
                  </Form.Group>
                  <Form.Group className="Input">
                      <Form.Control type="text" name="email" placeholder="Email" ref={this.email} />
                  </Form.Group>
                  <br></br>

                  <Form.Group className="dropdown">
                      <Form.Label>Select a Category:</Form.Label>
                      <Form.Control as="select" ref={this.category}>
                          <option value="hardware">Hardware</option>
                          <option value="software">Software</option>
                          <option value="internet">Internet</option>
                          <option value="other">Other</option>
                      </Form.Control>
                  </Form.Group>
                  <br></br>

                  <Form.Group className="Issue">
                      <Form.Label>Please Describe Your Issue:</Form.Label>
                      <Form.Control as="textarea" rows="7" ref={this.content} />
                  </Form.Group>

                  <fieldset>
                      <Form.Group as={Row}>
                          <Form.Label className="radio" column sm={12}>
                              Select the Urgency Level:<br></br>
                          </Form.Label>
                          <Form.Check className="radioButtons"
                              type="radio"
                              label="Urgent"
                              name="selectedOption"
                              value="Urgent"
                              onClick={this.handleCheckBoxChange.bind(this, this.urgency)}     
                          />
                          <Form.Check className="radioButtons"
                              type="radio"
                              label="Standard"
                              name="selectedOption"
                              value="Standard"
                              onClick={this.handleCheckBoxChange.bind(this, this.urgency)} 
                          />
                          <Form.Check className="radioButtons"
                              type="radio"
                              label="Low Priority"
                              name="selectedOption"
                              value="Low Priority"
                              onClick={this.handleCheckBoxChange.bind(this, this.urgency)} 
                          />
                      </Form.Group>
                  </fieldset>

                  <Button variant="secondary" type="button" className="submit" onClick={this.addTicket}>Submit Ticket</Button>
              </form>
          </div>
      );
  }
}

export default Home;

Upvotes: 0

95faf8e76605e973
95faf8e76605e973

Reputation: 14191

The issue is that you are pointing this.urgency to all of your Radio components 1 by 1. Here is a brief simulation of running your code from top to bottom:

<Form.Group as={Row}>
  <Form.Label className="radio" column sm={12}>
    Select the Urgency Level:<br></br>
  </Form.Label>
  <Form.Check
    value="Urgent"
    ref={this.urgency} // <-- this.urgency is now pointing to this 1st component
  />
  <Form.Check
    value="Standard"
    ref={this.urgency} // <-- this.urgency is now pointing to this 2nd component
  />
  <Form.Check
    value="Low Priority"
    ref={this.urgency} // <-- this.urgency is now pointing to this 3rd component
  />
</Form.Group>

So the final reference of this.urgency when the code is finished running is the 3rd component. So when you access this.urgency.current.value it will always return the 3rd component's value (i.e., Low Priority)

In React, you normally use state to hold these values - use ref sparsely and only if you really have to.

Here is an example of a solution:

constructor(props) {
  super(props);
  this.state = {
    tickets: [],
    urgency: "" // state for urgency
  };

<Form.Group as={Row}>
  <Form.Label className="radio" column sm={12}>
    Select the Urgency Level:<br></br>
  </Form.Label>
  <Form.Check
    value="Urgent"
    onChange={() => this.setState({ urgency: "Urgent" })}
  />
  <Form.Check
    value="Standard"
    onChange={() => this.setState({ urgency: "Standard" })}
  />
  <Form.Check
    value="Low Priority"
    onChange={() => this.setState({ urgency: "Low Priority" })}
  />
</Form.Group>

axios
  .post(url, {
    urgency: this.state.urgency
  })

Upvotes: 1

Related Questions