Adapted from w3schools & Pavlutin's guide to useRef & Demystifying react hooks
useRef only returns one item: an Object called current.
const testRef = useRef(1)
means testRef = { current: 1 }
useRef will assign a reference for each component, while a variable defined outside a function component scope will only assigned once.
Persistent values between renders
useRef does not trigger a re-render when its reference is updated, unlike useState. Counting how many times our app renders with the useState Hook would would be impossible since the hook itself would cause a re-render each time the count state is updated, and get stuck in an infinite loop. This is why we need to use useRef for storing mutable values instead.
Useful for keeping track of previous state values and state changes (that does not need to be updated on the screen)
Use cases: logging button clicks, stopwatch, media playback (play/pause)
Key difference between using outer scope variables and useRef for keeping track of mutable values: an outer scope variable would be global for all components, whereas useRef would only reference/track the state of that one component instance (click here to see the difference)
DOM manipulation
TLDR: Use useRef when you need information that is available regardless of component lifecycle and whose changes should NOT trigger rerenders. Use useState for information whose changes should trigger rerenders.
There are two key differences between reference and state:
From a higher point of view, references store infrastructure data of side-effects, while the state stores information that is directly rendered on the screen.
const address_container = useRef(reference_data_type)
return (
<div>
<input ref={address_container} type="text" />
</div>);
When we assign address_ container
to the input ref property, it creates a pointer reference to the input DOM element. This reference can also be used in other components. For instance, a reference can be passed down from parent to child via forwardRef (R1, R2).)
function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
inputEl.current.focus();
};
return (
<>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>);
}
const { useRef } = React;
const MyComponent = () => {
const nameRef = useRef();
const focus = () => {
nameRef.current.focus();
}
const blur = () => {
nameRef.current.blur();
}
return (
<section className="box">
<label for="name">Enter a name:</label>
<input ref={nameRef} type="text" name="name" id="name"/>
<button onClick={focus}>Focus!</button>
<button onClick={blur}>Remove Focus</button>
</section>
);
}
ReactDOM.render(<MyComponent />, document.getElementById('root'))
Definition of a controlled component -
...in the controlled component the form input element’s values and mutations are totally driven by event handlers and the value of the input element is always inferred from the state
whereas an uncontrolled component -
doesn't use any states on input elements or any event handler ... doesn't care about an input element’s real-time value changes.
In short, the state of controlled components are controlled by React, vs. the state of uncontrolled components which are controlled by the DOM. Connecting a managed state with input value makes that input value a controlled component. Refs are used in uncontrolled components to access the input values. Uncontrolled components may be easier to use for smaller applications, but controlled components offer more effective control and consistency which is advantageous for bigger applications. React recommends using controlled components for implementing forms.
When a controlled input value is undefined
, it essentially becomes uncontrolled, which triggers this error:
...refs are a necessary evil that helps us take the liberty of solving problems for which React itself can’t provide solutions due to its data-driven design philosophy ~Sameer Kumar
React uses a declarative/functional approach to programming. Apparently React hooks are an "aberration" to this approach, but necessary since components need a way to manage states and change events, which aren't possible just with pure functions. Using them still helps separate the relatively pure and impure parts of your code. But we need to be mindful of the correct scenarios to be using useRef so it does not descend into chaos.
It is important to refrain from directly manipulating the DOM while using React, since React uses a virtual DOM system (a lightweight copy of the actual DOM.) React syncs state changes in the virtual DOM with the actual DOM, but not the other way around. React will behave unpredictably if direct DOM changes are made without properly notifying React (is there a way to notify React though? TBD.)
The following screenshots are excerpts from this link.
var numbers = [1, 2, 3, 4, 5, 6];
var sum;
// Imperative
sum = 0;
for (let i = 0; i < numbers.length; i++) {
if (i % 2 === 0) {
sum += numbers[i] * 2;
}
}
console.log(sum); // 18
// Declarative
sum = numbers
.filter(i => i % 2)
.map(i => i * 2)
.reduce((acc, next) => acc + next);
console.log(sum); // 18
// Even more declarative
const isPair = i => i % 2;
const double = i => i * 2;
const sum = (a, b) => a + b;
sum = numbers.filter(isPair).map(double).reduce(sum);// 18
Functional programming is a form of declarative programming that builds software by composing pure functions, avoiding side-effects and using immutable data.(1) It is declarative as "a computation's logic is expressed without describing its control flow". (2) This stackoverflow post describes SQL as "a great example of the functional way of programming, which is a restricted subset of declarative programming in which the desired computation is specified by composing functions."
React useRef Hook
The Complete Guide to useRef() and Refs in React
6 Practical Applications for useRef
React useRef Hook Focus Example
Why need useRef and not mutable variable?
React Uncontrolled Elements With “useRef” Hooks
New React Documentation: Do Not Abuse Ref
React v18: useRef — What, When and Why? : Taming React’s necessary evil — useRef
Demystifying React Hooks: useRef
*What are controlled and uncontrolled components in React JS? Which one to use?
Controlled vs uncontrolled React components - why not both?
Imperative and Declarative Programming: In-depth comparison with examples
React is Declarative - What Does it Mean?
선언형 VS 명령형, 리액트가 선언형인 이유
Practical Functional Programming with Javascript: Great overview of core principles
Functional Programming with React/Redux