Frontend Development 15 min read

React Forms: Using Refs (Translation)

This article translates Loren Stewart’s guide on using React refs for form handling, explaining both controlled components and ref‑based approaches, and provides detailed code examples for text, number, select, radio, and checkbox inputs, including techniques for parent‑child communication and value extraction.

Hujiang Technology
Hujiang Technology
Hujiang Technology
React Forms: Using Refs (Translation)

React is a JavaScript library for building user interfaces, originally created by Facebook for Instagram and open‑sourced in May 2013. It offers high performance and simple logic, making it popular for form handling in many projects.

There are two standard ways to obtain values from a <form> element in React: using controlled components or using the ref attribute.

Controlled components bind the displayed value to component state and update it via an onChange handler. Below is a typical controlled component example:

import React, { Component } from 'react';

class ControlledCompExample extends Component {
  constructor() {
    super();
    this.state = { fullName: '' };
  }
  handleFullNameChange = (e) => {
    this.setState({ fullName: e.target.value });
  }
  handleSubmit = (e) => {
    e.preventDefault();
    console.log(this.state.fullName);
  }
  render() {
    return (
Full Name
);
  }
}

export default ControlledCompExample;

The main advantages of controlled components are easy validation and dynamic rendering of other components based on the input value. Their drawback is the amount of boilerplate code required, especially for large or complex forms.

Using ref provides a simpler way to read values directly from the DOM. The article then demonstrates several ref‑based patterns.

1. Text, Number, and Select Inputs

The simplest ref usage is assigning an arrow function to the ref attribute of an input element, storing the DOM node on the component instance:

<input type="text" ref={input => this.fullName = input} />

Similarly for a number input:

<input type="number" ref={cashMoney => this.amount = cashMoney} />

Values can then be accessed via this.fullName.value or this.amount.value . A select element works the same way:

<select ref={select => this.petType = select} name="petType">
  <option value="cat">Cat</option>
  <option value="dog">Dog</option>
  <option value="ferret">Ferret</option>
</select>

The selected value is retrieved with this.petType.value .

2. Passing Values from Child to Parent via Props

When a child component renders an input, the parent can still obtain the DOM node by passing a ref‑callback through props:

import React, { Component } from 'react';

class RefsForm extends Component {
  handleSubmit = (e) => {
    e.preventDefault();
    console.log('first name:', this.firstName.value);
    this.firstName.value = 'Got ya!';
  }
  render() {
    return (
this.firstName = input} />
);
  }
}

function CustomInput(props) {
  return (
{props.label}:
);
}

export default RefsForm;

Here the parent stores the child’s input node in this.firstName , allowing direct access and manipulation.

3. Radio Button Collections

Radio inputs share the same name attribute, forming a group. To retrieve the selected value, set a ref on the form , then access the group via the form reference:

import React, { Component } from 'react';

class RefsForm extends Component {
  handleSubmit = (e) => {
    e.preventDefault();
    const { pet } = this.form; // pet is the radio collection
    console.log(pet, pet.value);
  }
  render() {
    return (
this.form = form}>
Cat
Dog
Ferret
);
  }
}

export default RefsForm;

The same pattern works when the radio inputs are rendered inside child components.

4. Checkbox Collections

Checkbox groups may have multiple selected values, requiring a few more steps:

Attach a ref to the form .

Extract the checkbox node list (e.g., pet ).

Convert the node list to an array.

Filter for checked boxes.

Map the filtered nodes to their value attributes.

import React, { Component } from 'react';

class RefsForm extends Component {
  handleSubmit = (e) => {
    e.preventDefault();
    const { pet } = this.form;
    const checkboxArray = Array.prototype.slice.call(pet);
    const checkedCheckboxes = checkboxArray.filter(input => input.checked);
    console.log('checked array:', checkedCheckboxes);
    const checkedCheckboxesValues = checkedCheckboxes.map(input => input.value);
    console.log('checked array values:', checkedCheckboxesValues);
  }
  render() {
    return (
this.form = form}>
Cat
Dog
Ferret
);
  }
}

export default RefsForm;

The same logic can be abstracted into a reusable CheckboxSet component, as shown in the article.

Conclusion

If you do not need real‑time monitoring of form values or custom validation on every change, using ref to read form data can reduce the amount of code compared to controlled components. However, for complex forms with dynamic rendering or validation, controlled components may still be preferable. The article encourages experimenting with the examples to fully understand the trade‑offs.

frontendJavaScriptreactFormsRefsControlled Components
Hujiang Technology
Written by

Hujiang Technology

We focus on the real-world challenges developers face, delivering authentic, practical content and a direct platform for technical networking among developers.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.