728x90
반응형
01. 데이터 구조
const folderData = [
{
id: 1,
name: "Root Folder",
children: [
{
id: 2,
name: "Sub Folder 1",
children: [
{ id: 3, name: "File 1" },
{ id: 4, name: "File 2" }
]
},
{
id: 5,
name: "Sub Folder 2",
children: [
{ id: 6, name: "File 3" }
]
}
]
}
];
02. 재귀 컴포넌트 구조
import React from 'react';
const FolderItem = ({ item }) => {
return (
<div>
<div>{item.name}</div>
{item.children && item.children.length > 0 && (
<div style={{ marginLeft: '20px' }}>
{item.children.map(child => (
<FolderItem key={child.id} item={child} />
))}
</div>
)}
</div>
);
};
const FolderTree = ({ data }) => {
return (
<div>
{data.map(folder => (
<FolderItem key={folder.id} item={folder} />
))}
</div>
);
};
export default FolderTree;
03. 폴더 열림 관리
> state( openFolder )로 관리
> openFolder객체 : 키 = 폴더의 id / 값은 true/false
import React, { useState } from 'react';
const FolderItem = ({ item, isOpen, onToggle }) => {
const handleClick = () => {
onToggle(item.id);
};
return (
<div>
<div onClick={handleClick} style={{ cursor: 'pointer' }}>
{item.name} {isOpen ? '[-]' : '[+]'}
</div>
{isOpen && item.children && item.children.length > 0 && (
<div style={{ marginLeft: '20px' }}>
{item.children.map(child => (
<FolderItem
key={child.id}
item={child}
isOpen={isOpen}
onToggle={onToggle}
/>
))}
</div>
)}
</div>
);
};
const FolderTree = ({ data }) => {
const [openFolders, setOpenFolders] = useState({});
const handleToggle = (id) => {
setOpenFolders(prevState => ({
...prevState,
[id]: !prevState[id]
}));
};
return (
<div>
{data.map(folder => (
<FolderItem
key={folder.id}
item={folder}
isOpen={!!openFolders[folder.id]} //!! 연산자로 boolean값으로 사용
onToggle={handleToggle}
/>
))}
</div>
);
};
export default FolderTree;
04. 폴더를 닫았다가 열 때도, 기존에 열었던 특정 폴더 상태 유지
> 로컬 스토리지 ( 새로고침해도 상태 유지) --> 이걸로 선택
> 세선 스토리지에 (브라우저 세션 동안 상태 유지)
> 리코일 (persist- persist 추후)
import React, { useState, useEffect } from 'react';
const folderData = [
{
id: 1,
name: "Root Folder",
children: [
{
id: 2,
name: "Sub Folder 1",
children: [
{ id: 3, name: "File 1" },
{ id: 4, name: "File 2" }
]
},
{
id: 5,
name: "Sub Folder 2",
children: [
{ id: 6, name: "File 3" }
]
}
]
}
];
const FolderItem = ({ item, isOpen, onToggle }) => {
const handleClick = () => {
onToggle(item.id);
};
return (
<div>
<div onClick={handleClick} style={{ cursor: 'pointer' }}>
{item.name} {isOpen ? '[-]' : '[+]'}
</div>
{isOpen && item.children && item.children.length > 0 && (
<div style={{ marginLeft: '20px' }}>
{item.children.map(child => (
<FolderItem
key={child.id}
item={child}
isOpen={!!openFolders[child.id]}
onToggle={onToggle}
/>
))}
</div>
)}
</div>
);
};
const FolderTree = ({ data }) => {
const [openFolders, setOpenFolders] = useState({});
useEffect(() => {
// 페이지가 로드될 때 로컬 스토리지에서 상태를 불러옵니다.
const savedState = JSON.parse(localStorage.getItem('openFolders')) || {};
setOpenFolders(savedState);
}, []);
useEffect(() => {
// 상태가 변경될 때 로컬 스토리지에 상태를 저장합니다.
localStorage.setItem('openFolders', JSON.stringify(openFolders));
}, [openFolders]);
const handleToggle = (id) => {
setOpenFolders(prevState => ({
...prevState,
[id]: !prevState[id]
}));
};
return (
<div>
{data.map(folder => (
<FolderItem
key={folder.id}
item={folder}
isOpen={!!openFolders[folder.id]}
onToggle={handleToggle}
/>
))}
</div>
);
};
const App = () => {
return (
<div>
<h1>Folder Structure</h1>
<FolderTree data={folderData} />
</div>
);
};
export default App;
05. 데이터 새로고침 버튼
> state(folders) :
const FolderTree = () => {
const [openFolders, setOpenFolders] = useState({});
const [folders, setFolders] = useState([]);
useEffect(() => {
const loadInitialData = async () => {
const initialData = await fetchAndUpdateFolders();
setFolders(initialData);
};
loadInitialData();
}, []);
useEffect(() => {
const savedState = JSON.parse(localStorage.getItem('openFolders')) || {};
setOpenFolders(savedState);
}, []);
useEffect(() => {
localStorage.setItem('openFolders', JSON.stringify(openFolders));
}, [openFolders]);
const handleToggle = (id) => {
setOpenFolders(prevState => ({
...prevState,
[id]: !prevState[id]
}));
};
const handleRefresh = async () => {
const updatedData = await fetchAndUpdateFolders();
setFolders(updatedData);
};
return (
<div>
<button onClick={handleRefresh}>Refresh Data</button>
{folders.map(folder => (
<FolderItem
key={folder.id}
item={folder}
isOpen={!!openFolders[folder.id]}
onToggle={handleToggle}
/>
))}
</div>
);
};
끝.
반응형
'React' 카테고리의 다른 글
[React] 드래그 가능한 사이즈 조절 컴포넌트 구현 (2) | 2024.09.22 |
---|---|
페이지네이션 (0) | 2024.08.12 |
리액트 : Redux-toolkit 다크모드 (with. Tailwindcss) (0) | 2024.03.24 |
리액트 : 반응형 사이드 바 (햄버거 메뉴 🍔 ) (0) | 2024.01.02 |
React : 리액트 쿼리 LifeCycle (+ isLoading, isFetching) (0) | 2023.12.21 |