You're reading from React Key Concepts
Introduction
React.js is all about building user interfaces, and, in the context of this book, it's about building web user interfaces specifically.
Web user interfaces are ultimately all about the Document Object Model (DOM). You can use JavaScript to read or manipulate the DOM. This is what allows you to build interactive websites: you can add, remove, or edit DOM elements after a page was loaded. This can be used to add or remove overlay windows or to read values entered into input fields.
This was already discussed in Chapter 1, React – What and Why, and, as you learned there, React is used to simplify this process. Instead of manipulating the DOM or reading values from DOM elements manually, you can use React to describe the desired state. React then takes care of the steps needed to achieve this desired state.
However, there are scenarios and use cases wherein, despite using React, you still want to be able to directly reach out to specific DOM elements...
A World without Refs
Consider the following example: you have a website that renders an input field, requesting a user's email address. It could look something like this:
The code for the component that's responsible for rendering the form and handling the entered email address value might look like this:
function EmailForm() { const [enteredEmail, setEnteredEmail] = useState(''); function updateEmailHandler(event) { setEnteredEmail(event.target.value); } function submitFormHandler(event) { event.preventDefault(); // could send enteredEmail to a backend server } return ( <form className={classes.form} onSubmit={submitFormHandler}> <label htmlFor="email">Your email</label> <input type="...
Refs versus State
Since refs can be used to get quick and easy access to DOM elements, the question that might come up is whether you should always use refs instead of state.
The clear answer to this question is "no".
Refs can be a very good alternative in use cases like the one shown above, when you need read access to an element. This is very often the case when dealing with user input. In general, refs can replace state if you're just accessing some value to read it when some function (a form submit handler function, for example) is executed. As soon as you need to change values and those changes must be reflected in the UI (for example, by rendering some conditional content), refs are out of the game.
In the example above, if, besides getting the entered value, you'd also like to reset (i.e., clear) the email input after the form was submitted, you should use state again. While you could reset the input with the help of a ref, you should not do that...
Using Refs for More than DOM Access
Accessing DOM elements (for reading values) is one of the most common use cases for using refs. As shown above, it can help you reduce code in certain situations.
But refs are more than just "element connection bridges"; they are objects that can be used to store all kinds of values—not just pointers at DOM objects. You can, for example, also store strings or numbers or any other kind of value in a ref:
const passwordRetries = useRef(0);
You can pass an initial value to useRef()
(0
in this example) and then access or change that value at any point in time, inside of the component to which the ref belongs:
passwordRetries.current = 1;
However, you still have to use the current
property to read and change the stored value, because, as mentioned above, this is where React will store the actual value that belongs to the Ref.
This can be useful for storing data that should "survive" component re-evaluations...
React and Where Things End up in the DOM
Leaving the topic of refs, there is one other important React feature that can help with influencing (indirect) DOM interaction: Portals.
When building user interfaces, you sometimes need to display elements and content conditionally. This was already covered in Chapter 5, Rendering Lists and Conditional Content. When rendering conditional content, React will inject that content into the place in the DOM where the overall component (in which the conditional content is defined) is located.
For example, when showing a conditional error message below an input field, that error message is right below the input in the DOM:
This behavior makes sense. Indeed, it would be pretty irritating if React were to start inserting DOM elements in random places. But in some scenarios, you may prefer a (conditional) DOM element to be inserted...
Summary and Key Takeaways
- Refs can be used to gain direct access to DOM elements or to store values that won't be reset or changed when the surrounding component is re-evaluated.
- Only use this direct access to read values, not to manipulate DOM elements (let React do this instead).
- Components that gain DOM access via refs, instead of state and other React features, are considered uncontrolled components (because React is not in direct control).
- Prefer controlled components (using state and a strictly declarative approach) over uncontrolled components unless you're performing very simple tasks such as reading an entered input value.
- Using forward refs, you can also expose features of your own components such that they may be used imperatively.
- Portals can be used to instruct React to render JSX elements in a different place in the DOM than they normally would.
What's Next?
At this point in the book, you've encountered many...
Apply What You Have Learned
With this newly gained knowledge about refs and portals, it's again time to practice what you have learned.
Below, you'll find two activities that allow you to practice working with refs and portals. As always, you will, of course, also need some of the concepts covered in earlier chapters (e.g., working with state).
Activity 7.1: Extract User Input Values
In this activity, you have to add logic to an existing React component to extract values from a form. The form contains an input field and a drop-down menu and you should make sure that, upon form submission, both values are read and, for the purpose of this dummy app, output to the browser console.
Use your knowledge about Refs and uncontrolled components to implement a solution without using React state.
Note
You can find the starting code for this activity at https://packt.link/PAvKn. When downloading this code, you'll always download the entire repository. Make sure...