I wrote a script that loads data from 2 tables.
Using this script I need to just match corresponding elements in these 2 columns.
I am using angular-ui-tree for managing columns, but can't come up with an idea how to visually and programmatically match corresponding elements between 2 trees?
Thanks
Not quite sure what is your problem here. I assuming by "matching visually" you do not mean you need some AI API to actually do visual match, so you just want to get objects that are in the same location in the UI tree?
Using $nodeScope (type: Scope of ui-tree-node) should give you that information, as the property of $nodeScope is something like "1.1.1" or "1.1.2" etc. So you can just parse the "parent" node to get all children belonging to same node.
Scope also has a method isParent(nodeScope) which can check if a certain node (that calls the method) is a parent of targeted node. Similarly Scope has isSibling(targetNodeScope) and isChild(targetNodeScope) methods to help you identify the relationships. As a general guide, you just follow the (array) of nodes in a (nested) loop and pick the elements or objects you need. You can pick the objects from both UI trees at the same time, so they should be from the same node at that point.
Related
As far as I've read parents should store childrens data which would solve my problem simply because I could iterate through the tree, but I'm not able to come up with a solution that manages to do that in react.
To clarify:
My goal is to convert my JSX-Layout to a JSON-Object so that I can send it to my backend for further processing.
Currently each of the nodes handle the adding of a new child in themself. All nodes only know their immediate children.
The problem now is that I don't know how I could read the entire tree data structure.
For example: In Java I could simply add a child to a node by just accessing the node's reference and adding the new node to the list of childrens. Since I use functional components in React I'm not able to do that and probably need to pass down a event from the parent nodes to register new nodes from children but I simply cant wrap my head around it. I don't see how that is possible with React, but I'm certain that it's just me misunderstanding something or trying for too long.
Any help is appreciated!
TL;DR:
How do I manage state in trees so that I can access the whole tree and add/remove children to/from children and their descendants?
I tried to pass down an event from the parent through the whole hierarchy where every child would add its children but I'm not sure if that is correct since it seems really unclean.
If I'm understanding your question correctly, you want a way to traverse your tree. There are various ways to traverse a tree to generate a full depiction of its elements (to make a JSON object, for example), but I think you probably want to use in-order traversal. Here is a link with more details about some different tree traversal strategies.
If you're looking for a way to access a React component's children, you can read this article for inspiration.
That's obvious that for the diffing algorithm in React keys are essential. But I was wandering, why React just can't automatically generate keys based on the content we iterate over?
I also assume that items can share some similarity, or cab be identical in terms of content, but isn't it possible to generate keys once user open a page and somehow attach them to the items, so it is stable?
Or maybe there where attempts to solve the problem, if so, I would be grateful if you share it to me.
Update
Thank you guys for your answers, I've learnt a lot!
Also a thing I had in mind: what we developers do when there is no stable id (e.g. user added an item which is not yet saved into DB). In the cases we just generate id, and attach it to the object, or element in an array, but we do not generate ids on a fly, so it remains stable over time.
What if React just generate ids for all arrays which are involved into rendering process, in other words, arrays which are directly used in render function?
It can be done only once, during phase Commit phase, or whatever. Also I believe, the id can be readonly, or something, so user can't erase the id.
p.s.s
While I was writing p.s. question above, I realized, autogenerating id for arrays wouldn't work, since I've missed two things. All side effect react can do only during the Commit phase, but not Render phase. But that's not the main problem.
The main problem is when we use filtering or sorting on a back-end side. Since we receive a new array, filtered one, we would need to regenerate ids for those elements, but basically, that's the same html elements, in which we can change content to match filtering order. That's the same as Slava Knyazev mentioned.
React can't generate keys, because the entire point of keys is for you to help React track elements during it's tree-diffing stage.
For example, lets say you have the following code, where you naively use content instead of identifiers for your keys:
const people = usePeople(); // [{ id: "1", name: "James"}, {id: "2", name: "William"}]
return <ul>{people.map(p => <li key={p.name}>{p.name}</li>}</ul>
The above code will function and behave as you would expect. But what happens if the name of a person changes? To understand it, lets look at the tree it generates:
ul
li(James) James
li(William) William
If James becomes Josh between renders, the new tree will look like this:
ul
li(Josh) Josh
li(William) William
React will compare the two results and conclude the following:
li(James) is to be removed
li(Josh) is to be added
However, if we set our key prop to p.id, then the old and new tree will look as follows, respectively:
ul
li(1) James
li(2) William
ul
li(1) Josh
li(2) William
And when React compares the two, it will identify that James has become Josh, and needs only the text adjusted.
In the first scenario, the <li> component is completely destroyed, and a completely new component takes its place. Both of these actions run a complete React lifecycle for the component. In the second, it remains untouched, and only the text inside changes.
While in this contrived scenario, the performance penalty in the first case in minimal, it may be very significant with complex components.
I believe, unless your data is 100% certainly going to sort in one way and never change, key={index} isn't a good key (which is what I assume you want your auto-generated keys to be). You'd ideally want something that is unique to each item, regardless of the order.
It's explained in more detail in the new beta react docs https://beta.reactjs.org/learn/rendering-lists#where-to-get-your-key
I think what you are implying is React could potentially choose to use something like a stable hash (say sha1 on a serialised string or something) on the object to generate a unique key. I think this actually would work in many cases, and even gave me pause for thought for a while! Your question is actually a really good one, and a deep one.
However, it wouldn't work in every case. I think it would work only on a static object which has no methods or anything attached. On a JS object, not all properties are enumerable. Hashing something could only ever happen on the enumerable objects of properties, but the dev may have non-enumerable yet-still-unique methods attached to these objects. In fact, even enumerable methods cant really be serialised reliably and they could be what makes the object unique. Not to mention the complexities of reliably hashing something with prototypical inheritance involved.
I suspect there's also a performance aspect to this. Hashing is cheap, but no that cheap. Most cases can be keyed by just referencing a unique ID in the object, which is vastly cheaper. When enumerating a very large number of objects, these things matter, and so its better to defer to the developer. After all, if you really do want to hash it, its just one function call in userland -- and this saves great confusion on developer side when it doesn't work. The Principle of least astonishment comes to mind.
There's also an aspect of how this would limit the power of how expressive JSX can be due to it basically allowing free-form JS. You would probably have to supply some low level <React.Map> component primitives in order for react to supply this default key handling which implies you are a bit more restrained on what you can and can't do (complex functional chains).
I am making an MEAN stack app and use Mongoose alongside Mongo. I am struggling with organizing my objects in database. All works as expected but I have a feeling that the way I am doing things is wrong, but can't seem to find any resources on the topic that could help me, thus I hope somebody with some experience can share it with me.
I use Mongoose to create several schemas, and there is one dilemma I am facing, concerning nested objects in MongoDB.
Let's say I have a model that looks like that:
ParentSchema:{
property1:String,
children:[{}]
}
So, property1 is just some string, 'children' is an array that will contain objects of type 'Child' with some other properties, but also another array (f.ex. 'grandchildren:[{]} ), this time with another type of objects (Grandchild).
Child and Grandchild have no schemas and do not exist outside of the Parent, and will most likely be unique to each instance of Parent, so two Parents would not be sharing a Child object.
In my app, I am able to use urls such as '/parent/:id1/Child/:id2/Grandchild/:id3', where 'id1' is an actual id of Parent that Mongo generates, while 'id2' is an index of Child object instance stored in Parents array. The same goes for instances of Grandchildren stored inside Child object.
I was thinking that maybe having separate schemas for all 3 objects, and just saving references to objects is the way to go, like this:
ParentSchema:{
prop1:String,
children:[{type:ObjectId, ref:'Child'}]
}
ChildSchema:{
prop1:String,
granchildren:[{type : ObjectId, ref: 'Grandchild'}]
}
GrandChildSchema:{
prop1:String,
prop2:String
}
..but was unsure, as for me it implies that Child and GrandChild instances would be shared between different parents, however it seems easier to work with.
To sum up, I would like to know is:
which approach should I choose and why: first, second or maybe some other that I do not know about yet.
If I were to choose the second approach, should I create a separate API route for each of the objects?
How would I go about creating then? My wish is for the process to look like so:
Start creating Parent -> start creating first Child -> create some Grandchildren ->
finish creating Child -> start creating second Child -> ... -> finish creating Parent.
I apologize if the question is somehow weird, I will try to clarify as best as I can if required.
I would go with the second approach for a couple of reasons:
Schemas have better readability in my opinion.
They allow for data validation which you lack in the first approach.
Please note the answer below is primarily opinion based.
For the API design:
I think its really up to you as to which paths to expose to the consumer, since you've stated Child and Grandchild do not have the right to exist without a parent - I think your routes are fine as they are.
And finally - your process for creating these entities look fine to me. I would do the same thing myself.
Getting a bit stuck here on the idea...
I'm trying to create a flash card game / study material program where users are able to load lists of questions/answers. I want to organize the lists in a folder-like system. I imagine folders as arrays and the lists of questions and answers as text files.
My problem is that I know that with a single array, I can dynamically create an infinite amount of arrays... but how do I write data to the last array in the line? The idea is that the USER creates their own organization (dynamic, for different classes, subjects, etc)
I thought about something like myArray[i][j][k][l] but I don't know how to make it dynamic, such as if it was like myArray[3][4] has no subclasses or child arrays, or if [l] had 20 more subclasses/child arrays.
I was thinking about writing a function that has a loop that calls itself if there are children, but, I don't know how to make said unique for [i], [j], [k], etc.
Sorry if the information is a bit underwhelming, but I'm not sure how to express any more information.
Actionscript is object oriented and I will not try to create an array if it has to be dynamic. I will create an object called 'Questions' and will have the question text, text file location or whatever you want to maintain. I will create an ArrayCollection attribute called children with in the 'Question' class, which in turn is a list of Question objects. This way I can maintain hierarchy and add and remove children without much hassle.
I'm interested in using db4o as my persistence mechanism in my Desktop application but I'm concerned about a couple things.
1st concern: Accidentally clipping very complex object graphs.
Say I have a tree with a height of 10 and I fetch the root, how does it handle me storing the root object again?
From my understanding, it doesn't fetch the entire tree it fetches the first 5 referenced layers.
So.. If I make a trivial change to the root and then store it, will it clip away the nodes further down the tree, in essence deleting them.
If not.. how does it handle this?
2nd concern: Extracting subgraphs in a larger object graph
Using my tree example from above... If the database contains 1 massive tree can I query for a single node within it? Since .store was called only once, does my database think it contains only 1 "record"?
Thank you.
You have to be very careful, because two things can happen: you can pull whole db into memory, or just partial graph (rest of objects will be null).
In db4o there's notion of Activator and Update depth, which can be configured upon dbv40 configuration, or when objects are fetched. Its the way you tell db40 how deep you want him to go when fetching referenced objects. Check db4o web site, there's documentation about it:
http://developer.db4o.com/Resources/view.aspx/Reference/Object_Lifecycle/Activation
http://developer.db4o.com/Resources/view.aspx/Reference/Object_Lifecycle/Update_Depth
DB4O's Transparent Activation should resolve most of the fears you've expressed here.