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:
const [files, setFiles] = useState([]);
//AWS Setup
useEffect(() => {
Amplify.configure({
Auth:{
identityPoolId: '',
region: 'us-east-1',
},
Storage: {
AWSS3: {
bucket:'',
region: 'ca-central-1',
}
}
});
},[]);
//gets all files in the bucket
useEffect(() => {
Storage.list('').then(files => {
const s3_files = setFiles(files);
s3_files.replace("\"eTag\":", "\"perfect\":");
console.log(s3_files);
}).catch(err => {
console.log(err);
});
},[]);
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.
CodePudding user response:
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>
);
}
CodePudding user response:
I hope you, you used to reactjs. please before push data to array. check the current object is available.