Author avatar

Gaurav Singhal

Implementing a Radio List with Text Input in React

Gaurav Singhal

  • Jun 15, 2020
  • 6 Min read
  • 67 Views
  • Jun 15, 2020
  • 6 Min read
  • 67 Views
Web Development
Front End Web Development
Client-side Framework
React

Introduction

Forms seem pretty easy to build in plain HTML, but when it comes to JavaScript frameworks like React, it can be a bit tricky. React expects you to manage the form data yourself using state, instead of relying on the DOM to maintain the form data.

When you have a fixed set of input fields, it is easy to add them in your component; but dynamic fields can be challenging as you need to maintain the fields in the state. In this guide, you will learn how to create a dynamic radio list using a text input.

Start With The Component Class

Since all the form data needs to be handled by state, create properties in state to store the text input and radio list value. Also, initialize an empty array in state to store the radio options.

1
2
3
4
5
6
7
class App extends Component {
  state = {
    textValue: "",
    checkedOptionValue: "",
    options: [],
  };
}
jsx

Create the text input to add the radio options along with an Add button.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class App extends Component {
  state = {
    textValue: "",
    checkedOptionValue: "",
    options: [],
  };

  render() {
    return (
      <div className="App">
        <input
          type="text"
          value={textValue}
          onChange={(e) => this.setState({ textValue: e.target.value })}
        />
        <button onClick={this.handleOptionAdd}>Add</button>
      </div>
    );
  }
}
jsx

When the user clicks on the Add button, push the text value into the options state. Only push the text value if its length is greater than zero; otherwise, you will end up with radio options with empty values. Another thing to note here is that you need to store the option as an object of label and value.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
handleOptionAdd = () => {
  const { options, textValue } = this.state;
  if (textValue.trim().length === 0) return;
  this.setState({ textValue: "" });
  this.setState({
    options: [
      ...options,
      {
        label: textValue,
        value: textValue.toLowerCase().replace(" ", "-"),
      },
    ],
  });
};
jsx

Rendering the Radio List

To render the radio list, use the map() method to iterate over the options state array. Ensure that all the radio inputs have the same name prop so that the user can only check one radio input.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const { options, checkedOptionValue } = this.state;
//
{
  options.map((option) => (
    <div>
      <input
        type="radio"
        name="dynamic-radio"
        value={option.value}
        checked={checkedOptionValue === option.value}
        onChange={this.handleRadioChange}
      />
      <label>{option.label}</label>
    </div>
  ));
}
jsx

Complete Component Code

Check out the entire code for the component in this section.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import React, { Component } from "react";
import "./styles.css";

class App extends Component {
  state = {
    textValue: "",
    checkedOptionValue: "",
    options: [],
  };

  handleOptionAdd = () => {
    const { options, textValue } = this.state;
    this.setState({ textValue: "" });
    this.setState({
      options: [
        ...options,
        {
          label: textValue,
          value: textValue.toLowerCase().replace(" ", "-"),
        },
      ],
    });
  };

  handleRadioChange = (e) =>
    this.setState({ checkedOptionValue: e.target.value });

  render() {
    const { options, textValue, checkedOptionValue } = this.state;
    return (
      <div className="App">
        <input
          type="text"
          value={textValue}
          onChange={(e) => this.setState({ textValue: e.target.value })}
        />
        <button onClick={this.handleOptionAdd}>Add</button>

        <div>
          {options.map((option) => (
            <div>
              <input
                type="radio"
                name="dynamic-radio"
                value={option.value}
                checked={checkedOptionValue === option.value}
                onChange={this.handleRadioChange}
              />
              <label>{option.label}</label>
            </div>
          ))}
        </div>
      </div>
    );
  }
}

export default App;
jsx

Implementation Using Hooks

You can implement the same thing using the useState hook in a functional component. Store the options, textValue, and radioValue in separate state variables, and the rest of the component works similarly to the class component.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import React, { useState } from "react";
import "./styles.css";

function App() {
  const [options, setOptions] = useState([]);

  const [textValue, setTextValue] = useState("");

  const [radioValue, setRadioValue] = useState("");

  const handleOptionAdd = () => {
    if (textValue.trim().length === 0) return;
    setTextValue("");
    setOptions([
      ...options,
      { label: textValue, value: textValue.toLowerCase().replace(" ", "-") },
    ]);
  };

  return (
    <div className="App">
      <input
        type="text"
        value={textValue}
        onChange={(e) => setTextValue(e.target.value)}
      />
      <button onClick={handleOptionAdd}>Add</button>

      <div>
        {options.map((option) => (
          <div>
            <input
              type="radio"
              name="dynamic-radio"
              value={option.value}
              checked={radioValue === option.value}
              onChange={(e) => setRadioValue(e.target.value)}
            />
            <label>{option.label}</label>
          </div>
        ))}
      </div>
    </div>
  );
}

export default App;
jsx

Conclusion

It is vital when building forms in React that you think in terms of state and how to manage the form data using state. Relying on the DOM to handle the form data can lead to unpredictable results, making the code difficult to test. Handling the radio list in React is a bit different from what you usually do in HTML, but it gets easier to set up in React once you understand how to deal with values in the state.

1