pic1
pic2
pic3
When I select one item, I want to apply the new style of one item and the original style of the rest of the items
Example
when I click SubBookmark33
Current
pic1 -> pic2
But I want to
pic1 -> pic3
BookmarksFolder.js
import BookmarksFolderNode from './BookmarksFolderNode';
import classes from './BookmarksFolder.module.css';
import { folders } from '../../resources/data';
function BookmarksFolder() {
return (
<div className={classes.bookmarksFolder}>
{folders.map((folder) => (
<BookmarksFolderNode
key={folder.id}
folder={folder}
/>
))}
</div>
);
}
export default BookmarksFolder;
BookmarksFolderNode.js
import { useState, useRef } 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 tab = useRef();
const img = useRef();
const title = useRef();
const selectFolderHandler = () => {
tab.current.style.backgroundColor = '#1a73eb';
img.current.src = OpenedFolder;
title.current.style.color = '#1a73eb';
};
const openFolderHandler = () => {
setFolderIsOpen((prevState) => !prevState);
};
const paddingLeft = 20 * (props.folder.depth - 1);
return (
<div className={classes.bookmarksFolderNode}>
<div className={classes.bookmarksMainFolderNode}>
<div className={classes.verticalTab} ref={tab}></div>
<div className={classes.innerContainer} style={{paddingLeft}}>
<div className={classes.icon} onClick={openFolderHandler}>
{folderIsOpen ? (
<AiFillCaretDown className={classes.ironIcon} />
) : (
<AiFillCaretRight className={classes.ironIcon} />
)}
</div>
<img src={Folder} className={classes.folderIcon} ref={img} />
<div
className={classes.menuLabel}
onClick={selectFolderHandler}
ref={title}
>
{props.folder.title}
</div>
</div>
</div>
<div className={classes.bookmarksSubFolderNode}>
{props.folder.subFolder &&
props.folder.subFolder.map((subFolder) => (
<BookmarksFolderNode key={subFolder.id} folder={subFolder} />
))}
</div>
</div>
);
}
export default BookmarksFolderNode;
data.js
export const folders = [
{
id: 1,
depth: 1,
title: 'Bookmark 1',
subFolder: [
{
id: 1,
depth: 2,
title: 'SubBookmark 1',
subFolder: [
{
id: 1,
depth: 3,
title: 'SubBookmark 11',
},
{
id: 2,
depth: 3,
title: 'SubBookmark 22',
},
{
id: 3,
depth: 3,
title: 'SubBookmark 33',
subFolder: [
{
id: 1,
depth: 4,
title: 'SubBookmark 111',
},
],
},
],
},
{
id: 2,
depth: 2,
title: 'SubBookmark 2',
},
],
},
];
The idea is that, when you select a folder, you should deselect the others from parent component BookmarksFolder
. The solution is a little bit tricky because you select the folder using BookmarksFolderNode
local state (I mean folderIsOpen
).
Well, lets start to use parent component's state to select/deselect folder:
import BookmarksFolderNode from './BookmarksFolderNode';
import classes from './BookmarksFolder.module.css';
import { folders } from '../../resources/data';
function BookmarksFolder() {
const [foldersSelected, setFoldersSelected] = useState(new Array(folders.length).fill(false));
const selectFolder = (index) => {
let result = new Array(folders.length).fill(false);
result[index] = true;
setFoldersSelected(result);
}
return (
<div className={classes.bookmarksFolder}>
{folders.map((folder, index) => (
<BookmarksFolderNode
key={folder.id}
folder={folder}
isSelected={foldersSelected[index]}
select={(index) => selectFolder(index)}
index={index}
/>
))}
</div>
);
}
export default BookmarksFolder;
So now in BookmarksFolderNode
we have to use isSelected
and select
instead of folderIsOpen
and openFolderHandler
. Not only but we have to replicate the same logic for subfolders:
import { useState, useRef, useEffect } 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 [subfoldersSelected, setSubFoldersSelected] = useState(new Array(props.folder.subFolder.length).fill(false));
const tab = useRef();
const img = useRef();
const title = useRef();
useEffect(() => {
if (props.isSelected) {
tab.current.style.backgroundColor = '#1a73eb';
img.current.src = OpenedFolder;
title.current.style.color = '#1a73eb';
}
else {
tab.current.style.backgroundColor = 'black';
img.current.src = Folder;
title.current.style.color = 'black';
}
}, [props.isSelected])
const openFolderHandler = () => {
props.select(props.index)
};
const paddingLeft = 20 * (props.folder.depth - 1);
const selectSubfolder = (index) => {
let result = new Array(props.folder.subFolder.length).fill(false);
result[index] = true;
setSubFoldersSelected(result);
}
return (
<div className={classes.bookmarksFolderNode}>
<div className={classes.bookmarksMainFolderNode}>
<div className={classes.verticalTab} ref={tab}></div>
<div className={classes.innerContainer} style={{paddingLeft}}>
<div className={classes.icon} onClick={openFolderHandler}>
{props.isSelected ? (
<AiFillCaretDown className={classes.ironIcon} />
) : (
<AiFillCaretRight className={classes.ironIcon} />
)}
</div>
<img src={Folder} className={classes.folderIcon} ref={img} />
<div
className={classes.menuLabel}
onClick={openFolderHandler}
ref={title}
>
{props.folder.title}
</div>
</div>
</div>
<div className={classes.bookmarksSubFolderNode}>
{props.folder.subFolder &&
props.folder.subFolder.map((subFolder, index) => (
<BookmarksFolderNode key={subFolder.id} folder={subFolder} index={index} isSelected={subfoldersSelected[index]} select={(index) => selectSubfolder(index)} />
))}
</div>
</div>
);
}
export default BookmarksFolderNode;
So now, if you select a folder (or a subfolder) the others folder (or subfolders) will be deselected and the useEffect
will apply the desidered css.