我正在嘗試使用 MUI TreeView 組件顯示樹資料。我有一個物件傳遞給 RenderTreeWithCheckboxes 函式。如果我宣告全域變數資料并傳入函式 RenderTreeWithCheckboxes,那么我的代碼可以正常作業。但是,如果我確實從 API 和 setState 為我的變數獲取資料,我的代碼將不起作用。我認為問題是因為組件是在我的資料成功獲取之前呈現的。這是我的代碼
我在 CodeSanBox 中也有代碼:https ://codesandbox.io/s/quizzical-feather-oyg9f0?file=/src/App.js
import { useEffect, useState } from "react";
import "./styles.css";
import axios from "axios";
import TreeView from "@mui/lab/TreeView";
import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
import ChevronRightIcon from "@material-ui/icons/ChevronRight";
import TreeItem from "@mui/lab/TreeItem";
import { Checkbox, FormControlLabel } from "@mui/material";
const category = {
id: "0",
termName: "T?t c? chuyên m?c",
subTermTaxonomies: [
{
id: 1,
termName: "Kh?ng có chuyên m?c",
description: "Kh?ng có chuyên m?c",
subTermTaxonomies: []
},
{
id: 2,
termName: "Tin t?c chung",
description: "Chuyên m?c Tin t?c chung",
subTermTaxonomies: []
},
{
id: 3,
termName: "H??ng nghi?p",
description: "Chuyên m?c H??ng nghi?p",
subTermTaxonomies: []
},
{
id: 4,
termName: "Tin tuy?n sinh",
description: "Chuyên m?c Tin tuy?n sinh",
subTermTaxonomies: []
},
{
id: 5,
termName: "??i h?c FPT",
description: "Tr??ng ??i h?c FPT",
subTermTaxonomies: [
{
id: 6,
termName: "??i h?c FPT - Hà N?i",
description: "??i h?c FPT - Hà N?i",
subTermTaxonomies: []
},
{
id: 7,
termName: "??i h?c FPT - ?à N?ng",
description: "??i h?c FPT - ?à N?ng",
subTermTaxonomies: []
},
{
id: 8,
termName: "??i h?c FPT - TP. H? Chí Minh",
description: "??i h?c FPT - TP. H? Chí Minh",
subTermTaxonomies: []
},
{
id: 9,
termName: "?ai h?c FPT - C?n Th?",
description: "?ai h?c FPT - C?n Th?",
subTermTaxonomies: []
},
{
id: 10,
termName: "?ai h?c FPT - Quy Nh?n",
description: "?ai h?c FPT - Quy Nh?n",
subTermTaxonomies: []
}
]
}
]
};
export default function App() {
const [category, setCategory] = useState({});
const [selected, setSelected] = useState([]);
function getChildById(node, id) {
let array = [];
//returns an array of nodes ids: clicked node id and all children node ids
function getAllChild(nodes) {
if (nodes === null) return [];
array.push(nodes.id);
if (Array.isArray(nodes.subTermTaxonomies)) {
nodes.subTermTaxonomies.forEach((node) => {
array = [...array, ...getAllChild(node)];
array = array.filter((v, i) => array.indexOf(v) === i);
});
}
return array;
}
//returns the node object that was selected
function getNodeById(nodes, id) {
if (nodes.id === id) {
return nodes;
} else if (Array.isArray(nodes.subTermTaxonomies)) {
let result = null;
nodes.subTermTaxonomies.forEach((node) => {
if (!!getNodeById(node, id)) {
result = getNodeById(node, id);
}
});
return result;
}
return null;
}
return getAllChild(getNodeById(node, id));
}
function getOnChange(checked, nodes) {
//gets all freshly selected or unselected nodes
const allNode = getChildById(category, nodes.id);
//combines newly selected nodes with existing selection
//or filters out newly deselected nodes from existing selection
let array = checked
? [...selected, ...allNode]
: selected.filter((value) => !allNode.includes(value));
setSelected(array);
}
const RenderTreeWithCheckboxes = (nodes) => {
return (
<TreeItem
key={nodes.id}
nodeId={nodes.id.toString()}
label={
<FormControlLabel
control={
<Checkbox
checked={selected.some((item) => item === nodes.id)}
onChange={(event) =>
getOnChange(event.currentTarget.checked, nodes)
}
//onClick={(e) => e.stopPropagation()}
/>
}
label={<>{nodes.termName}</>}
key={nodes.id}
/>
}
>
{Array.isArray(nodes.subTermTaxonomies)
? nodes.subTermTaxonomies.map((node) =>
RenderTreeWithCheckboxes(node)
)
: null}
</TreeItem>
);
};
const fetchCategoryHandler = async () => {
const response = await axios.get(
`https://news-feamsapi.tranduydat.com/api/term-taxonomy/get-ref`,
{
headers: {
Authorization: `Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJmYmE3OTdjNC1hZGRmLTQ0MDEtOTIzOC01NDNlZTMxNWI5MTAiLCJlbWFpbCI6ImR1Y2xvbmcya3p6QGdtYWlsLmNvbSIsIm5hbWUiOiJidWkgZHVjIGxvbmciLCJqdGkiOiJhYTFhMGVlYi02NGE3LTRiMTAtYjgxMi01OGU1N2RhMTQ1NDgiLCJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2xhaW1zL3JvbGUiOiJVc2VyIiwiZXhwIjoxNjY5MTEzMzI3LCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjUwMDEiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjQyMDAifQ.i-G56xKTM432C7D1xcVJHJXkktOCxG3KdmU8WdhcyZs`
}
}
);
const data = response.data.data;
const transformData = { id: "0", termName: "", subTermTaxonomies: [] };
transformData.subTermTaxonomies = data;
setCategory(transformData);
};
useEffect(() => {
fetchCategoryHandler();
console.log("category", category);
}, []);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<TreeView
name="category"
defaultCollapseIcon={<ExpandMoreIcon />}
defaultExpanded={["0"]}
defaultExpandIcon={<ChevronRightIcon />}
>
{RenderTreeWithCheckboxes(category)}
</TreeView>
</div>
);
}
我已經學會了使用 useEffect 并在 useEffect 中獲取資料,但仍然一切都無法正常作業。我想通過從 API 獲取資料而不是硬編碼來呈現我的組件
uj5u.com熱心網友回復:
需要添加條件來檢查是否nodes?.id
存在
{nodes?.id && (
<TreeItem
.....
</TreeItem>
)}
</>
https://codesandbox.io/s/compassionate-sound-3s5n2j?file=/src/App.js:2052-2924
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/520572.html
下一篇:狀態未轉移到另一個組件時出現問題