Lesson 5

Navigating User Input: Exploring Refs, Controlled and Uncontrolled Components in React

Introduction and Topic Overview

Welcome! Today's journey explores how React handles user input in functional components. We will cover Refs, a feature for managing certain functionalities, as well as the difference between controlled and uncontrolled components.

Understanding User Input in Functional Components

User input is crucial for all interactive web applications. React handles this input elegantly, using state, props, and hooks. Let's construct a Greeting function component that presents a dynamic message based on user input.

In this component, useState is used to declare the state variable name. The name stores the value of the input element and updates whenever the text input changes:

JavaScript
1import React, { useState } from 'react'; 2 3function Greeting() { 4 const [name, setName] = useState(''); 5 6 return ( 7 <div> 8 <h1>Hello, {name}!</h1> 9 <input 10 type="text" 11 value={name} 12 onChange={(event) => setName(event.target.value)} // Updates `name` upon typing in the input 13 /> 14 </div> 15 ); 16}
Introduction to Refs in React

Refs or references in React provide a way to access and interact with DOM nodes or React elements directly within your components. This is especially handy in cases where you want to change the child component without making use of props or triggering a re-render.

Refs are created by invoking the useRef hook provided by React. Here's how we do it:

JavaScript
1const myRef = useRef();

Notice that we call useRef() without passing any arguments. This results in myRef.current getting initialized with the value of null. The current property is mutable; it's created specifically for you to assign it a persistent value that doesn't trigger a re-render, thereby allowing the value to persist across renders.

Let’s see how the ref is used with an actual element in JSX by using the ref attribute, which takes the ref created above as its value:

JavaScript
1<input ref={myRef} type="text" />

The ref attribute acts like a tether, linking the myRef ref to the input field, hence allowing us detailed access to this specific instance of the input field across renders. It lets myRef.current point to the corresponding DOM node, here an HTMLInputElement, providing a way to read from or write to it.

Following is a brief example:

JavaScript
1import React, { useRef } from 'react'; 2 3function Greeting() { 4 const nameRef = useRef(); // nameRef.current is initialized as null 5 6 return ( 7 <div> 8 <h1>Hello, {nameRef.current && nameRef.current.value}!</h1> 9 <input ref={nameRef} type="text" /> {/* ties nameRef to the input field */} 10 </div> 11 ); 12}

As we can see, the text input is now linked with nameRef. Although in this form React does not automatically capture and update its value, opening up interesting possibilities we'll look at next.

Controlled vs Uncontrolled Components

Controlled inputs are connected to React state, and they change when the state changes. Conversely, uncontrolled inputs store their state internally and are not controlled by React. Although the state is more commonly controlled by components, uncontrolled components are useful in some scenarios, such as file uploads.

React provides flexibility in how we can create components in terms of handling user input. Both controlled and uncontrolled components serve different purposes and are utilized based on the specific needs of your application.

Creating Uncontrolled Components

When creating uncontrolled components, we let the form field keep track of its own value, rather than updating the value based on the application’s state. Here's an example of an uncontrolled component:

JavaScript
1import React, { useRef } from "react"; 2 3function UncontrolledComponent() { 4 const inputRef = useRef(); // Creates a ref 5 6 function handleSubmit(e) { 7 e.preventDefault(); 8 alert(inputRef.current.value); // Reads directly from the DOM 9 } 10 11 return ( 12 <form onSubmit={handleSubmit}> 13 <input ref={inputRef} type="text" /> 14 <button type="submit">Submit</button> 15 </form> 16 ); 17}

In this case, inputRef.current points directly to the input DOM element, enabling you to read its value directly.

Creating Controlled Components

When creating controlled components, we let React's state handle the input field’s value. Here’s an example of a controlled component:

JavaScript
1import React, { useState } from "react"; 2 3function ControlledComponent() { 4 const [name, setName] = useState(''); // Creates a state variable 5 6 function handleSubmit(e) { 7 e.preventDefault(); 8 alert(name); 9 } 10 11 return ( 12 <form onSubmit={handleSubmit}> 13 <input 14 type="text" 15 value={name} 16 onChange={e => setName(e.target.value)} // Sets the state variable when the input changes 17 /> 18 <button type="submit">Submit</button> 19 </form> 20 ); 21}

In this case, the input field’s value is controlled by the name state variable, and it updates via the onChange handler.

Each of these methods has its own use case scenarios and can be useful in different situations. It's essential to understand both approaches, so you can be effective in managing data input and flow within your React applications.

Working with Nested Functional Components

Nested components allow us to break down components into smaller, more reusable parts. Various parent-child relationships exist in React. For instance, if People is considered a parent component, Person would be its child:

JavaScript
1function Person({ name }) { 2 return <p>Hello, {name}!</p>; 3} 4 5function People() { 6 const names = ['Alice', 'Bob', 'Charlie']; 7 8 return ( 9 <div> 10 {names.map((name) => ( 11 <Person key={name} name={name} /> // Child components 12 ))} 13 </div> 14 ); 15}

Any changes in parent components will consequently affect their nested child components.

Quick Lesson Summary and Further Practice

Congratulations on learning to handle user inputs in React functional components! We have covered state, props, refs, hooks, and the distinction between controlled and uncontrolled components.

Up next are the hands-on tasks for you to practice! Enjoy coding with React!

Enjoy this lesson? Now it's time to practice with Cosmo!

Practice is how you turn knowledge into actual skills.