Reputation: 260
I don't speak English very well. Please be understanding!
First, please check my code!
export default function DriveFolder() {
const [clickFolderPk, setClickFolderPk] = useState(1);
const viewFolder = async () => {
const url = `/api/store/drive/view-folder?folderId=${clickFolderPk}`;
await get(url)
.then((res) => {
console.log(res);
setMainFolder(res.directChildrenFolders);
})
.catch((error) => {
console.log(error);
});
};
useEffect(() => {
viewFolder();
}, [clickFolderPk]);
return (
<div className={classes.driveFolder}>
{mainFolder.map((main, key) => (
<TreeView>
<TreeItem
onClick={() => setClickFolderPk(main.FOLDER_PK)}>
<TreeItem nodeId='10' label='OSS' />
<TreeItem nodeId='6' label='Material-UI'>
<TreeItem nodeId='7' label='src'>
<TreeItem nodeId='8' label='index.js' />
<TreeItem nodeId='9' label='tree-view.js' />
</TreeItem>
</TreeItem>
</TreeItem>
</TreeView>
))}
</div>
);
}
I edited some code to make it clear. (might misspelled)
With this code, on the first rendering, since 'clickFolderPk' value is 1, I get the right data from DB.
However, since I have subfolders within folders from 'clickFolderPk' value 1, I have to request another GET REQUEST to see my subfolders from root folders.
Here is the simple image that you can understand my situation better.
this is what I get from 'clickFolderPk' value 1.
However, when I press 'kikiki', GET request functions and render like this.
This is not the way I want to render things.
I want every data from DB, however they don't disappear whenever I use different GET request with different PK number.
I want them stay on the screen and get the subfolders within them.
I'm struggling with this issue for quite a time.
Your help will be really appreciated!!!!!
Upvotes: 0
Views: 28
Reputation: 173
It's all about Nesting: Folders have sub-folders, etc and it goes on...
Note: To break things down, I will answer from a React point of view disregarding how your backend api is structured or returns data.
Basically there are two main approaches,
Approach #1:
The global state is a single source of truth for all the folders think of it like this:
const [allFolders, setAllFolders] = useState([
{
id: "1",
name: "a-1",
folders: [
{
name: "a-subfolder-1",
folders: [{ name: "a-subfolder-subfolder-1" }],
},
{ name: "subfolder-2" },
],
},
]);
The problem is that any small update requires to mutate the entire state. So I will focus more on Approach #2
Approach #2:
There is the main tree that has child components, child components can expand and have children too:
import { useEffect, useState } from "react";
import "./styles.css";
export default function DriveFolder() {
const [folders, setFolders] = useState([
{ id: "1", name: "folder-a" },
{ id: "2", name: "folder-b" },
{ id: "3", name: "folder-c" }
]);
return (
<div style={{ display: "flex", flexDirection: "column" }}>
{folders.map((folder) => {
return <Folder key={folder.id} folder={folder} />;
})}
</div>
);
}
const Folder = ({ parent = undefined, folder }) => {
const [subfolders, setSubfolders] = useState([]);
const [isOpened, setOpened] = useState(false);
const hasSubfolders = subfolders.length > 0;
useEffect(() => {
// send request to your backend to fetch sub-folders
// --------------- to ease stuff I will hard code it
// with this you can limit the example of nest you wish
const maxNestsCount = 5;
const subfolderParent = parent || folder;
const subfolder = {
id: subfolderParent.id + "-sub",
name: "subfolder-of-" + subfolderParent.name
};
const currentNestCount = subfolder.name.split("-sub").length;
setSubfolders(currentNestCount < maxNestsCount ? [subfolder] : []);
// -----------------------------
}, []);
const handleToggleShowSubFolders = (e) => {
e.stopPropagation();
if (!hasSubfolders) {
return;
}
setOpened(!isOpened);
};
return (
<div
style={{
display: "flex",
flexDirection: "column",
paddingHorizontal: 5,
marginTop: 10,
marginLeft: parent ? 20 : 0,
backgroundColor: "#1678F230",
cursor: hasSubfolders ? "pointer" : undefined
}}
onClick={handleToggleShowSubFolders}
>
{folder.name}
<div style={{ display: isOpened ? "block" : "none" }}>
{subfolders.map((subfolder) => (
<Folder key={subfolder.id} parent={folder} folder={subfolder} />
))}
</div>
</div>
);
};
Try it out:
Here is the output of the sample code above:
Upvotes: 1