useRef
?In React, useRef
is a hook that provides a way to create a reference to a value or a DOM element that persists across renders but does not trigger a re-render when the value changes.
useRef
:useRef
persists between component re-renders. This means the value of a ref
does not get reset when the component re-renders, unlike regular variables.ref
(ref.current
) does not cause a component to re-render. This is different from state (useState
), which triggers a re-render when updated.import React, { useRef } from 'react';
function FocusInput() {
// Step 1: Create a ref to store the input element
const inputRef = useRef(null);
// Step 2: Define the function to focus the input
const handleFocus = () => {
// Access the DOM node and call the focus method
inputRef.current.focus();
};
return (
<div>
{/* Step 3: Attach the ref to the input element */}
<input ref={inputRef} type="text" placeholder="Click the button to focus me" />
<button onClick={handleFocus}>Focus the input</button>
</div>
);
}
export default FocusInput;
import React, { useEffect, useRef, useState } from 'react';
function Chat() {
const [messages, setMessages] = useState(["Hello!", "How are you?"]);
const chatBoxRef = useRef(null);
// Function to simulate adding new messages
const addMessage = () => {
setMessages((prevMessages) => [...prevMessages, "New message!"]);
};
// Scroll to the bottom whenever a new message is added
useEffect(() => {
chatBoxRef.current.scrollTop = chatBoxRef.current.scrollHeight;
}, [messages]);
return (
<div>
<div
ref={chatBoxRef}
style={{ height: "200px", overflowY: "scroll", border: "1px solid black" }}
>
{messages.map((msg, index) => (
<div key={index}>{msg}</div>
))}
</div>
<button onClick={addMessage}>Add Message</button>
</div>
);
}
export default Chat;
https://stackoverflow.com/questions/270612/scroll-to-bottom-of-div
Notice the re-renders in both of the following cases -
// ugly code
import React, { useState } from 'react';
function Stopwatch() {
const [time, setTime] = useState(0);
const [intervalId, setIntervalId] = useState(null); // Use state to store the interval ID
const startTimer = () => {
if (intervalId !== null) return; // Already running, do nothing
const newIntervalId = setInterval(() => {
setTime((prevTime) => prevTime + 1);
}, 1000);
// Store the interval ID in state (triggers re-render)
setIntervalId(newIntervalId);
};
const stopTimer = () => {
clearInterval(intervalId);
// Clear the interval ID in state (triggers re-render)
setIntervalId(null);
};
return (
<div>
<h1>Timer: {time}</h1>
<button onClick={startTimer}>Start</button>
<button onClick={stopTimer}>Stop</button>
</div>
);
}
export default Stopwatch;
// better code
import React, { useState, useRef } from 'react';
function Stopwatch() {
const [time, setTime] = useState(0);
const intervalRef = useRef(null);
const startTimer = () => {
if (intervalRef.current !== null) return; // Already running, do nothing
intervalRef.current = setInterval(() => {
setTime((prevTime) => prevTime + 1);
}, 1000);
};
const stopTimer = () => {
clearInterval(intervalRef.current);
intervalRef.current = null;
};
return (
<div>
<h1>Timer: {time}</h1>
<button onClick={startTimer}>Start</button>
<button onClick={stopTimer}>Stop</button>
</div>
);
}