'Reactjs Collapse / expand folder list and displaying data in 2 different ways
I have huge data set with a lot of nested parent/children arrays. My goal is to make these folders and data to look like this: Finished file/folder app. I am currently stuck achieving this:
Task 1: When I click once on a folder in the sidebar it should expand/collapse it's contents. The same click will also make the folder active.
Problem 1: It makes folder active only after few clicks, sometimes at first, it's completely random.
Task 2: When I click on a file or folder in the main area, it activates. When activated, it should also expand the path to the folder in the sidebar tree.
Problem 2: Main area work independently and I can go through folders only inside main and nothing happens in the sidebar (they should be connected to each other) as they are from sidebar to main (I mean when I click on sidebar folder or file, it opens up in main area but when I click on folder or item in the main area - it only changes in main area.
App.js:
import classes from "./App.module.css";
import React, { useState } from "react";
import Context from "./context";
import List from "./List";
import Item from "./Item";
function App(item) {
const [name, setName] = useState("");
const [type, setType] = useState("");
const [children, setChildren] = useState([]);
const [isExpandedApp, setIsExpandedApp] = useState(false);
const [activatedApp, setActivatedApp] = useState(false);
const onClick = (item) => {
setIsExpandedApp(!isExpandedApp);
setActivatedApp(!activatedApp);
setName(item.name);
setType(item.type);
item.type === "folder"
? setChildren(
item.children
.sort(function (a, b) {
if (a.name.toLowerCase() < b.name.toLowerCase()) return -1;
if (a.name.toLowerCase() > b.name.toLowerCase()) return 1;
return 0;
})
.map((x) => <Item key={x.id} item={x} />)
)
: setChildren("");
};
const providerValue = {
setChildren,
onClick,
isExpandedApp,
activatedApp,
};
return (
<Context.Provider value={providerValue}>
<header>
<h2>Home Assignment</h2>
</header>
<section>
<nav>
<List />
</nav>
{!children && (
<div className={classes.preview}>
<h1>Preview</h1>
<p>Name: {name}</p>
<p>Type: {type}</p>
</div>
)}
{children && (
<div className={classes.folderIsActive}>
<>
{children.map((x) =>
x.props.item.type !== "folder" ? (
<ul key={x.props.item.id} className={classes.centering}>
<ul
className={classes.oneLetter}
onClick={() => onClick(x.props.item)}
>
{x.props.item.name.charAt(0)}
</ul>
{x.props.item.name}
</ul>
) : (
<ul key={x.props.item.id} className={classes.centering}>
<ul
className={classes.greyFolder}
onClick={() => onClick(x.props.item)}
></ul>
{x.props.item.name}
</ul>
)
)}
</>
</div>
)}
</section>
</Context.Provider>
);
}
export default App;
List.js:
import React, { useEffect, useState } from "react";
import Item from "./Item";
export default function List() {
const [data, setData] = useState([]);
const getData = () => {
fetch("data.json", {
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
})
.then(function (response) {
return response.json();
})
.then(function (myJson) {
setData(myJson.response);
});
};
useEffect(() => {
getData();
}, []);
return (
<ul>
{data
.sort(function (a, b) {
if (a.name.toLowerCase() < b.name.toLowerCase()) return -1;
if (a.name.toLowerCase() > b.name.toLowerCase()) return 1;
return 0;
})
.map((x) => {
return <Item key={x.id} item={x} />;
})}
</ul>
);
}
Item.js:
import React, { useState, useContext } from "react";
import classes from "./App.module.css";
import Context from "./context";
export default function Item({ item }) {
const [isExpandedItem, setIsExpandedItem] = useState(false);
const [activatedItem, setActivatedItem] = useState(false);
const { onClick, isExpandedApp, activatedApp } = useContext(Context);
const setValues = () => {
setIsExpandedItem(isExpandedApp);
setActivatedItem(activatedApp);
};
const onItemClick = () => {
onClick(item);
setValues();
};
return (
<ul>
<li
tabIndex="0"
className={activatedItem ? classes.active : classes.notActive}
onClick={onItemClick}
>
{item.type === "folder" && (
<i
className={isExpandedItem ? classes.arrowDown : classes.arrowRight}
/>
)}
{item.name}
</li>
{isExpandedItem && item.children && (
<ul>
{item.children
.sort(function (a, b) {
if (a.name.toLowerCase() < b.name.toLowerCase()) return -1;
if (a.name.toLowerCase() > b.name.toLowerCase()) return 1;
return 0;
})
.map((x) => (
<Item key={x.id} item={x} />
))}
</ul>
)}
</ul>
);
}
Any tips would be really helpful!
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
