I'm a react.js beginner, searching for methods to alter my data structure. For example, I want to push new objects into the children-array or remove them by key.
What is the appropriate way to do that?
const [treeData, setTreeData] = useState([
{
title: "parent 1",
key: "0-0",
icon: <UserAddOutlined />,
children: [
{
title: "parent 1-0",
key: "0-0-0",
icon: <UserAddOutlined />,
children: [
{
title: "leaf",
key: "0-0-0-0",
icon: <UserAddOutlined />,
},
{
title: "leaf",
key: "0-0-0-1",
icon: <UserAddOutlined />,
},
],
},
{
title: "parent 1-1",
key: "0-0-1",
icon: <UserAddOutlined />,
children: [
{
title: "sss",
key: "0-0-1-0",
icon: <UserAddOutlined />,
},
],
},
],
},
]);
So you should not update the state directly. It is not allowed.
Maybe where you are receiving data from, suppose via api and the data is response.payload.data etc.
So in your case use the setTreeData(response.payload.data) method to add stuff in it.
Now if you want to update certain value (remove or update using index etc). Obviously you will have to have index somehow.
So for deleting say you will have some click and against that a handler for it
removeItem(e) {
item_to_remove = e.target..... etc // to get the item's reference for matching
setTreeData(treeData.filter(items => item.<someproperty> != item_to_remove))
// In your case could also be targetting children maybe
// setTreeData(treeData.Children.filter(items => item.<someproperty> != item_to_remove))
}
I would say maybe handle childrens' array inside another useState variable (childrenTreeData maybe). But you will have to look it's feasibility too. Just an idea after seeing your data
JUST for INFO
This is something similar I did for updating prices inside each cards in my project
const getCurrentPrice = useCallback(() => { // <======= maybe you do not need this
const updatedTilesData = tilesData.map((tile: any) => {
return {
...tile, // <======= get everything here and then update the price below for item
currentPrice: calculateDNCurrentPrice(
tile.startingPrice,
tile.dnTimestamp
),
};
});
setTilesData(updatedTilesData);
}, [tilesData]);
Hey I'm trying to implement nested drag&drop within re-order sequencesin my MERN app. I working to find ideal approach for mongodb data model and implement to Lexicographic order or linked lists for infinite sub folders. I used Model Tree Structures in this link but every node have limitless children for that require recursion and recursive functions or currying. Documentations not clear enough for make do that.
I want show all tree once and not sohuld appear after than click to arrow icon.There is my doodles for front side generation that working with only one depth such like graph nodes. Maybe Modified Preorder Tree Traversal implementation examples you have for this scenario.
const tree = data => { // immutable array
let ascendants = data.filter(d=>d.parent==null)
let descandants = data.filter(d=>d.parent)
**strong text**
let form = []
ascendants.map(a=>{
let node1 = {...a}; /// copying
let node1Children = [];
descandants.map(b=>{
let node2 = {...b};
if(node1._id == b.parent){
node1Children.push(node2)
}
})
node1.children = node1Children;
form.push(node1);
})
return form;
}
I cant take result with using $graphLookup because list format is not what i want.Could you give me some mongodb playground or grouping aggregate solutions? Below json examples shown my expecting results. I can do before but hardcode is unapropriate and performless. Is comparing good way?
[
// mongo database
{_id:123, title:'Books', slug:'books', parent:null },
{_id:124, title:'Programming', slug:'programming', parent:null },
{_id:125, title:'JavaScript', slug:'javascript', parent:'programming' },
{_id:126, title:'C++',slug:'cpp', parent:'programming' },
{_id:127, title:'React', slug:'react', parent:'javascript' },
{_id:128, title:'Redux', slug:'redux', parent:'react' },
{_id:129, title:'Toolkit', parent:'redux' },
{_id:130, title:'Saga', parent:'redux' },
{_id:131, title:'Nodejs', parent:'programming' },
{_id:132, title:'Databases', slug:'databases' },
{_id:133, title:'MongoDB', parent:'databases' },
]
[
// what i want
{ title: "Books"},
{ title: "Programming", parent:"computer-science", children: [
{ title: "JavaScript", children: [
{ title: "React", children: [
{ title: "Redux", children: [
{ title: "Saga" },
{ title: "Thunk" },
{ title: "Mobx" },
{ title: "Observable" },
{ title: "Context" },
{ title: "GraphQL" },
{ title: "Toolkit", children:[
{ title: "typescript" },
{ title: "slices", children:[
{ title: "createAsyncThunk" },
{ title: "createSlice" },
] },
] },
] },
{ title: "Nextjs" },
]},
{ title: "Vue", },
{ title: "angular", },
]},
{ title: "C++", },
{ title: "NodeJS", },
] },
{ title: "MongoDB", parent: "databases"},
]
You could create a Map to key your objects by slug. The values per key will be the result objects for parent objects. Include an entry for null, which will collect the top-level elements.
Then iterate the data again to populate children arrays -- when that property does not exist yet, create it on the fly. Finally output the top-level elements.
function makeTree(data) {
let children = []; // Top-level elements
let map = new Map(data.map(({title, slug}) => [slug, { title }]))
.set(null, {children});
for (let {slug, parent, title} of data) {
(map.get(parent || null).children ??= [])
.push(slug ? map.get(slug) : {title});
}
return children;
}
// Your mongodb data:
const data = [{_id:123, title:'Books', slug:'books', parent:null },{_id:124, title:'Programming', slug:'programming', parent:null },{_id:125, title:'JavaScript', slug:'javascript', parent:'programming' },{_id:126, title:'C++',slug:'cpp', parent:'programming' },{_id:127, title:'React', slug:'react', parent:'javascript' },{_id:128, title:'Redux', slug:'redux', parent:'react' },{_id:129, title:'Toolkit', parent:'redux' },{_id:130, title:'Saga', parent:'redux' },{_id:131, title:'Nodejs', parent:'programming' },{_id:132, title:'Databases', slug:'databases' },{_id:133, title:'MongoDB', parent:'databases' }];
console.log(makeTree(data));
I have created a demo using a tutorial that i have found.
This is the demo => https://codesandbox.io/s/strange-monad-otv0g?file=/src/language.js
In App.js the sidebar is receiving the array of objects as props, it all works fine
const sidebaritems = [
{
name: "first",
label: "First",
items: [
{ name: "sublink2", label: "SubLink 1" },
{ name: "sublink3", label: "SubLink 2" }
]
},
"divider",
{
name: "second",
label: "Second",
items: [
{ name: "subLink 1", label: "SubLink 1" },
{ name: "subLink 2", label: "SubLink 2" }
]
},
"divider",
{
name: "third",
label: "Third"
}
];
<SideBar items={sidebaritems} />
I want now to use an external data language file that i import where i have other translations and also sidebaritems to pass, so i have created language.js and imported in the App.js
import dataForTexts from "./language.js";
My question is, how can i pass from language.js the same sidebaritems in my sidebar component in app.js
You need a named import to import your dataForTexts . So change your import statement as
import { dataForTexts } from "./language.js";
Now pass the sidebaritems as
<SideBar items={dataForTexts.sidebaritems} />
As I understand it you need this. As items, you just need to pass your data from language.js (dataForTexts)
Quick info to describe the context.
I am working to a tree component that receives as prop this kind of data model:
workfolder: [{
label: "test",
folders: [
{ label: "label 1", id: 1 },
{ label: "label 2", id: 2 },
{ label: "label 3", id: 3 }
]
}];
All data are stored in a Redux store.
The initial value is:
state: { workfolder: [] }
On mount i fetch for default values and merge the results to workfolder in the reducer and i get my tree drawn.
return {
...state,
workfolder: results
}
When i click on one of the labels ( label 3 ) i fetch again for the sub-folders using the id and i get:
[{ label: "label 5", id: 5 },{ label: "label 5", id: 5 }]
At this point in the reducer i use a library to loop deep into the state till i find the property matching the id of the element i clicked ( label 3 in this case ) and want to merge the sub-folders into a new folder attribute.
let newState = JSON.parse(JSON.stringify(state.workfolder));
deepForEach( newState, (value, key, subject, path) => {
const isParentFolder = value === action.payload.parent;
const hasNotFolders = !subject.folders;
if( isParentFolder && hasNotFolders ) {
subject.folders = action.payload.node
}
} );
then i merge the new state in the store:
return {
...state,
workfolder: newState
}
Following this way i get the store updated, but the component won't redraw.
NOTE: this is a dummy example. In real life i have to deal with a multi level nested object having only the id and a string containing the path of the attribute i want to modify in the store.
The example that i found in the redux documentation shows how to do that writing statically the merge...
I have to draw a representation of data using collapsible tree structure, i am using below example link for my purpose :
http://fperucic.github.io/treant-js/examples/collapsable/
But the problem i am facing is the above link had images at every node, i want to replace it with text which when i am doing it is generating the tree with correct branches but the text is not appearing.I am using my json like this:
{
"name":"sourcetable",
"children":[{"name":"MARD"},{"name":"MARD"},{"name":"MARD"},{"name":"MARD"}]
}
It comes something like this:
Let me know how i can show the name labels on the collapsible tree.
I think you are missing a bit:
nodeStructure: {
text: { name: "Parent node" },
children: [
{
text: { name: "First child" }
},
{
text: { name: "Second child" }
}
]
}
Taken from here:
http://fperucic.github.io/treant-js/
var simple_chart_config = {
chart: {
container: "#OrganiseChart-simple"
},
nodeStructure: {
text: { name: "Parent node" },
children: [
{
text: { name: "First child" }
},
{
[enter image description here][1]text: { name: "Second child" }
}
]
}
};
Demo Link:
https://fperucic.github.io/treant-js/examples/super-simple