React访问元素同级节点:修改非当前li类名及Ref使用咨询
Got it, let's work through this. You want to update the className of all other <li> elements in the same <ul> when one is clicked, plus learn how to set up and access refs in your function context. Here's a practical implementation using React (since you're working with event handlers and refs, this is the most common context for this scenario):
Full Sample Code (Using a Single Ref for the )
This approach is clean and efficient—we use one ref to target the parent <ul>, then access all its child <li> elements:
import { useRef } from 'react'; function SelectableList() { // Create a ref to attach to our <ul> element const listContainerRef = useRef(null); const handleLiClick = (event) => { const clickedLi = event.currentTarget; const clickedText = clickedLi.innerText; // Safely add the 'pink' class to the clicked li (avoids duplicate classes) clickedLi.classList.add('pink'); // Get all <li> elements inside the parent <ul> const allListItems = listContainerRef.current.querySelectorAll('li'); // Loop through each li to update non-clicked ones allListItems.forEach(li => { // Use element comparison instead of text (more reliable if duplicate text exists) if (li !== clickedLi) { // Reset to your default class, or adjust as needed li.className = 'list-item'; // Alternative: Remove the pink class without resetting all classes // li.classList.remove('pink'); } }); }; return ( <ul ref={listContainerRef}> <li className="list-item" onClick={handleLiClick}>First Item</li> <li className="list-item" onClick={handleLiClick}>Second Item</li> <li className="list-item" onClick={handleLiClick}>Third Item</li> <li className="list-item" onClick={handleLiClick}>Fourth Item</li> </ul> ); } export default SelectableList;
Key Details Explained
Setting Up the Ref:
- We use
useRefto createlistContainerRef, then bind it to the<ul>via therefprop. This lets us access the actual DOM element later withlistContainerRef.current.
- We use
Handling the Click:
- We grab the clicked
<li>withevent.currentTarget, then safely add thepinkclass usingclassList.add()(this is better than concatenatingclassNamedirectly, as it prevents duplicate class names). - Using
querySelectorAll('li')on the<ul>ref gives us all sibling<li>elements in one go.
- We grab the clicked
Updating Other Lis:
- Instead of comparing text (which can fail if multiple lis have the same text), we compare the DOM elements directly with
li !== clickedLi. This ensures we only skip the exact element that was clicked. - You can either reset the
classNameto your default (likelist-item) or just remove thepinkclass withli.classList.remove('pink')—choose whichever fits your styling needs.
- Instead of comparing text (which can fail if multiple lis have the same text), we compare the DOM elements directly with
Alternative: Individual Refs for Each
If you need to access specific <li> elements directly (not just via the parent), you can store individual refs in an object:
import { useRef } from 'react'; function IndividualRefList() { // Create a ref object to hold refs for each li const listItemRefs = useRef({}); const handleLiClick = (event) => { const clickedLi = event.currentTarget; clickedLi.classList.add('pink'); // Loop through all stored li refs Object.values(listItemRefs.current).forEach(li => { if (li && li !== clickedLi) { li.classList.remove('pink'); } }); }; return ( <ul> <li className="list-item" ref={el => listItemRefs.current.item1 = el} onClick={handleLiClick}>Item 1</li> <li className="list-item" ref={el => listItemRefs.current.item2 = el} onClick={handleLiClick}>Item 2</li> <li className="list-item" ref={el => listItemRefs.current.item3 = el} onClick={handleLiClick}>Item 3</li> </ul> ); }
This approach is useful if you need to manipulate specific lis outside of the click handler, but the parent ref method is generally more scalable for this specific use case.
内容的提问来源于stack exchange,提问作者Kevin Danton

