Привет всем, у меня есть проблема или более того, я хочу знать: «Как я могу создать древовидную таблицу вне структуры, используя вложенный json». Без использования какой-либо третьей части lib/package
У меня есть вложенный json, как показано ниже:
[
{
"id": 1,
"name": "VehicleData",
"owner": "admin",
"sub_details": [
{
"sub_name": "Lexus",
"sub_id": 4,
},
{
"sub_name": "BMW",
"sub_id": 3,
}
]
},
{
"id": 2,
"name": "Mobiles,
"owner": "admin",
"sub_details": [
{
"sub_name": "Apple",
"sub_id": 2,
}
]
},
{
"id": 3,
"name": "Laptop",
"owner": "admin",
"sub_details": []
}
]
Что я пробовал: -
import React, {useState, useEffect} from 'react';
import classes from './TableData.module.css';
const TableData = () => {
const [oldData, newData] = useState([]);
useEffect(() => {
fetchData();
}, []);
const Id = (dataId) => {
alert(dataId);
};
const Name = (dataName) => {
alert(dataName);
};
const fetchData = async () => {
try {
const response = await fetch('someapi/json');
const data = await response.json();
newData(data);
} catch (e) {
console.warn(e)
}
}
const DisplayData = oldData.map((data) => {
return (
<tr key = {
data.id
}>
<td> {
data.id
} </td>
<td> {
data.name
} </td>
<td> {
data.owner
} </td>
<td>
<button onClick = {
() => Id(data.id)
}>getId</button>
<button onClick = {
() => Name(data.name)
}>getname</button>
</td>
</tr>
)
})
return (
<div>
<div>
<table>
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>owner</th>
</tr>
</thead>
<tbody> {DisplayData} </tbody>
</table>
</div>
</div>
)
}
export default TableData;
что я наделал : Я создал таблицу с помощью json, а также добавил кнопку для получения родительских данных.
что мне нужно и как я могу сделать:
Как я могу добавить создание вложенной структуры без использования сторонних плагинов, а также добавить кнопку в каждую строку.
Как я могу получить родительские данные и дочерние данные при нажатии кнопки каждой дочерней строки.
Как я могу переключать и держать открытой вложенную структуру.
если какой-либо URL-адрес информации есть, это будет здорово?
🤔 А знаете ли вы, что...
JavaScript активно развивается, и новые версии языка регулярно включают новые функции и улучшения.
В React вы должны разбивать свои данные на компоненты. Работа с данными как есть в многоуровневой вложенности считается плохим дизайном — подробное объяснение смотрите здесь.
Имея это в виду, я выделил по одному компоненту для каждого уровня вложенности. Таким образом, строка может управлять скрытым состоянием своей подстроки. Вот окончательный код — см. полную демонстрацию здесь — нажмите кнопку «переключить»:
index.js:
import React, { useState, useEffect } from "react";
import "./styles.css"
const Table = () => {
const [items, setItems] = useState([]);
useEffect(() => {
fetchData();
}, []);
const fetchData = async () => {
try {
const response = await fetch("./data.json");
const data = await response.json();
setItems(data);
} catch (e) {
console.warn(e);
}
};
return <div>
{
items.map((data) => {
return <TableData key = {data.id} data = {data} />
})
}
</div>;
};
const TableData = (props) => {
const data = props.data;
const [subHidden, setSubHidden] = useState(false);
const Id = (dataId) => {
alert(dataId);
};
const Name = (dataName) => {
alert(dataName);
};
const Toggle = () => {
setSubHidden(state => {
return !state;
});
};
return (
<div >
<span> {data.id} </span>
<span> {data.name} </span>
<span> {data.owner} </span>
<span>
<button onClick = {() => Id(data.id)}>getId</button>
<button onClick = {() => Name(data.name)}>getname</button>
<button onClick = {() => Toggle()}>toggle</button>
</span>
<TableSubDetails
subDetails = {data.sub_details}
style = {{ display: subHidden ? 'none' : 'block'}}
/>
</div>
);
}
const TableSubDetails = (props) => {
const subDetails = props.subDetails;
return (
<div className = "subData" style = {props.style}>
{
subDetails.map((subData) => {
return <div key = {subData.sub_id}>
<span> {subData.sub_id} </span>
<span> {subData.sub_name} </span>
</div>
})
}
</div>
);
}
export default Table;
стили.css:
.subData {
padding: 5px 15px;
}
Вот моя версия решения, обновив существующий код некоторой логикой.
const TableData = () => {
const [oldData, newData] = useState([]);
const [id, setId] = useState({});
useEffect(() => {
fetchData();
}, []);
const Id = (dataId) => {
alert(dataId);
};
const Name = (dataName) => {
alert(dataName);
};
const fetchData = async () => {
try {
newData(jsonData);
} catch (e) {
console.warn(e);
}
};
const updateId = useCallback((dataId) => {
setId((prevState) => {
let updatedState = { ...prevState };
const hasId = updatedState[dataId] ? true : false;
if (hasId) {
delete updatedState[dataId];
} else {
updatedState = { ...updatedState, [dataId]: dataId };
}
return {
...updatedState
};
});
}, []);
const renderTableRows = useCallback(
(details, isChild = false) => {
let renderData = [];
details.forEach((detail) => {
const detailId = isChild ? detail["sub_id"] : detail["id"];
const name = isChild ? detail["sub_name"] : detail["name"];
const childData = (
<tr key = {`${name}-${detailId}`}>
<td> {detailId} </td>
<td> {name} </td>
<td> {detail.owner} </td>
<td>
<button onClick = {() => Id(detailId)}>getId</button>
<button onClick = {() => Name(name)}>getname</button>
{detail.sub_details?.length > 0 && (
<button
onClick = {() => {
updateId(detailId);
}}
>
{id[detailId] === detailId ? "Hide" : "Show"} child
</button>
)}
</td>
</tr>
);
renderData.push(childData);
if (id[detailId] === detailId && detail.sub_details?.length > 0) {
const childData = renderTableRows(detail.sub_details, true);
renderData = [...renderData, ...childData];
}
});
return renderData;
},
[id, updateId]
);
const DisplayData = useMemo(() => {
return renderTableRows(oldData);
}, [oldData, renderTableRows]);
return (
<div>
<div>
<table>
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>owner</th>
</tr>
</thead>
<tbody> {DisplayData} </tbody>
</table>
</div>
</div>
);
};
export default TableData;
вот пример ссылка.
Спасибо