React中点击某一项时,如何为当前项应用新样式并为其余项恢复原有样式?
Got it, let's fix this single-selection issue! The problem right now is that each BookmarksFolderNode is handling its own selection state independently—so when you click one, others don't know to reset their styles. Here's how to fix it using React's state lifting pattern, which is perfect for this kind of shared state scenario:
Step 1: Lift Selection State to Parent Component (BookmarksFolder.js)
We'll move the selection state to the parent component so it can act as a single source of truth for all child nodes.
import BookmarksFolderNode from './BookmarksFolderNode'; import classes from './BookmarksFolder.module.css'; import { folders } from '../../resources/data'; import { useState } from 'react'; function BookmarksFolder() { // Track the ID of the currently selected folder const [selectedFolderId, setSelectedFolderId] = useState(null); // Handle selection events from child nodes const handleFolderSelect = (folderId) => { setSelectedFolderId(folderId); }; return ( <div className={classes.bookmarksFolder}> {folders.map((folder) => ( <BookmarksFolderNode key={folder.id} folder={folder} selectedId={selectedFolderId} onSelect={handleFolderSelect} /> ))} </div> ); } export default BookmarksFolder;
Step 2: Update Child Component to Use Props-Driven Styles (BookmarksFolderNode.js)
We'll remove direct DOM manipulation (an anti-pattern in React) and instead use props to conditionally apply styles. We'll also pass the selection state down to nested subfolders.
import { useState } from 'react'; import { AiFillCaretDown, AiFillCaretRight } from 'react-icons/ai'; import Folder from '../../resources/img/folder.svg'; import OpenedFolder from '../../resources/img/opened_folder.svg'; import classes from './BookmarksFolderNode.module.css'; function BookmarksFolderNode(props) { const [folderIsOpen, setFolderIsOpen] = useState(false); const openFolderHandler = () => { setFolderIsOpen((prevState) => !prevState); }; // Check if current folder is the selected one const isSelected = props.folder.id === props.selectedId; // Trigger parent's selection handler on click const selectFolderHandler = () => { props.onSelect(props.folder.id); }; const paddingLeft = 20 * (props.folder.depth - 1); return ( <div className={classes.bookmarksFolderNode}> <div className={classes.bookmarksMainFolderNode}> {/* Conditional style for vertical tab */} <div className={`${classes.verticalTab} ${isSelected ? classes.selectedTab : ''}`} ></div> <div className={classes.innerContainer} style={{paddingLeft}}> <div className={classes.icon} onClick={openFolderHandler}> {folderIsOpen ? ( <AiFillCaretDown className={classes.ironIcon} /> ) : ( <AiFillCaretRight className={classes.ironIcon} /> )} </div> {/* Conditional folder icon based on selection */} <img src={isSelected ? OpenedFolder : Folder} className={classes.folderIcon} /> {/* Conditional style for folder title */} <div className={`${classes.menuLabel} ${isSelected ? classes.selectedLabel : ''}`} onClick={selectFolderHandler} > {props.folder.title} </div> </div> </div> <div className={classes.bookmarksSubFolderNode}> {props.folder.subFolder && props.folder.subFolder.map((subFolder) => ( <BookmarksFolderNode key={subFolder.id} folder={subFolder} selectedId={props.selectedId} onSelect={props.onSelect} /> ))} </div> </div> ); } export default BookmarksFolderNode;
Step 3: Add Selected State Styles to CSS (BookmarksFolderNode.module.css)
Replace direct style manipulations with CSS classes for cleaner, more maintainable code:
/* Add these classes to your existing CSS */ .selectedTab { background-color: #1a73eb; } .selectedLabel { color: #1a73eb; }
Why This Works
- Single Source of Truth: The parent component controls which folder is selected, ensuring only one folder can be active at a time.
- Props-Driven Rendering: Styles are applied based on prop values, which aligns with React's declarative programming model (no more manual DOM tweaks).
- Recursive Support: Selection state and handlers are passed down to nested subfolders, so the single-selection behavior works across all levels of your folder hierarchy.
内容的提问来源于stack exchange,提问作者Lee

