When pushing data into a file tree, it pushes 2 sets of the same data and I am not exactly sure why.
I have a simple json array that looks like this:
export const treeDataFile = [{
type: 'directory',
name: '2022',
}]
export default treeDataFile;
I am trying to push 4 files I have into it like this by calling this function:
const addFileToTree = (file,i) => {
treeDataFile.push({type: i, name: file});
console.log(treeDataFile)
setFirstRender(true);
};
This is how addFileToTree is being called:
return (
<div classname="container">
<GeistProvider>
<CssBaseline />
<Tree style={{width:"280px", height: "500"}} value={treeDataFile} onClick={handleShow} />
</GeistProvider>
<table>
<tbody>
{files.map((file,i) => (
<tr key={file.key}>
{addFileToTree(file.key,i)}
</tr>
))}
</tbody>
</table>
</div>
);
};
The result has been this, there should only be 4 items, but it has duplicated it.
Any help would be greatly appreciated.
>Solution :
You’re mutating the global treeDataFile as a side effect of your component function (and even "worse", as a side effect of a render .map()). Among other things, this would cause treeDataFile to grow larger and larger every time your component is updated.
You’re also probably using React’s StrictMode, which double-renders your components to begin with to make sure you’re not doing anything silly, like you now are.
If your goal is to derive a treeDataFile for that tree component based on the global treeDataFile and files, you can do that with useMemo, which is a hook designed for deriving new data based on other data; in this case your "base" treeDataFile and the files you get. (I assume they’re props, since you don’t show. They could be state, too, of course.)
I elided the table from this component, since it didn’t have any real content based on the original code you had.
// could be imported just as well
const treeDataFile = [{
type: 'directory',
name: '2022',
}];
function Component({ files }) {
const treeWithFiles = React.useMemo(() => {
const tree = [...treeDataFile]; // shallow-copy
(files || []).forEach((file, i) => {
tree.push({ type: i, name: file });
});
return tree;
}, [treeDataFiles, files]);
return (
<div classname="container">
<GeistProvider>
<CssBaseline />
<Tree style={{ width: "280px", height: "500" }} value={treeWithFiles} onClick={handleShow} />
</GeistProvider>
</div>
);
}
