React DIV dynamic layout algorithm to create a box-in-box view - javascript

I am trying to represent the following onto a web page. - that is a data model representation illustrating objects, attributes and child objects in a parent child hierarchy.
I was thinking to create a generic React component that would be able to store a single data object, but then also have that same object accept child instances in a sort of dynamic mechanism.
The result would be a nested-box type view, which would show all elements and nested children.
the child div, would need to have some sort of layout feature (much like the grid-layout features of popular UI frameworks (material-ui, Scemantic-ui, Zurb foundation)
at the end, The "model" would look something like this.
I dont even know where to start to build something like this. I am looking for some ideas to build a UI like this... the intention at a later stage would be to enable something like React-draggable to allow dragging of elements.

For infinite tree structure rendering purposes, you might need to look at recursion usage in React. I found some resources for you:
https://dev.to/baso53/recursive-rendering-in-react-building-a-universal-json-renderer-f59
https://medium.com/#suraj.rajan/recursion-using-reactjs-components-3c871f99fb2f
Basically, you need to create a function in the class which returns an instance of your class.

Related

Angular: Proper way to inform nested property change between different components

I have an application that shows and manipulates users' information in a table with many columns. The user model has quite a few deep nested properties, each table column represent a property. To better explain, I created this simplified app at stackbliz. The real application has more columns and is relatively organised into more layers/components.
Basically, each column is a component that has an #Input person. While Location property value is changed by clicking itself, another component LOS needs to be aware of it and change its text colour, if location becomes 'J'.
Normally, this isn't working as the person reference of each #Input is not changed, so the change detection is not firing.
Please ignore the pipe used as it's just a way to show one component has to react if a property is changed in another component. I can mark it as impure but it seems not a good way as it will run too many times unnecessarily.
Also, I know I can make it work by using getter or a function to read the property in another component template, I have included the code as comment in stackblitz app. But it can unnecessarily run many times as well.
Question
I wonder if there is another better, cleaner and intuitive way to notify nested property changes between components. It could be a better way of organising the object and its property, passing them to different components, or other techniques that don't bring performance overheads.
Thanks in advance
Component Structure
You need a a RowComponent to segregate each row and its data and coloring of the LOS column (which may differ between rows).
After adding this component, I would not use LocationComponent or LengthofstayComponent as there is not much to them and your code will become cluttered with passing values between them.
Implementing the color changing
I recommend using a BehaviorSubject, a corresponding Observable and the async pipe. Every time the async pipe, emits, a change detection cycle will be intiated.
In RowComponent add:
showColorSubject = new BehaviorSubject<boolean>(false);
showColor$ = this.showColorSubject.asObservable();
If we call next on the Subject in changeLocation:
this.showColorSubject.next(this.person.location.code === "J");
then showColor$ will emit true/false accordingly in the RowComponent template where we use the async pipe to selectively enable the color class:
[class.color]="showColor$ | async"
Stackblitz
https://stackblitz.com/edit/so-color-row-cell?file=src%2Fapp%2Frow%2Frow.component.html
(Formatting is messed up but I'll leave that to you)

React: How to render only visible elements

I built a component, that gets a json in props, and display it, and the user can edit it, and with a lot of functionality, and looks like this:
When the user loads a big json, the render time of the component is very slow. So, I want to render only the visible elements, instead all elements in json, so it will be faster. (As you can see, there is a scrollbar when overflow-y).
I saw there are a lot of libraries which support what I want, like react-window, or react-virtualized etc. The problem is those libraries expect to receive a list of components, like this:
and in my component, all the components are nested in each other, like json, and very complex with the functionalities.
1) Is there a library which resolve my problem?
2) Is there another solution for the slow render, besides render only the visible elements?

The price of rendering elements using D3 in a React application?

I'm trying to understand how to integrate D3 and React. Specifically I'm trying to understand how using D3 to render visualizations impacts React. As explained in this excellent question and it's reply:
[...] there is currently no great way to work with React and D3 [...] this is because in the React world you don't do direct DOM manipulation, but in the d3 world that's the only thing you do.
The reply goes on to say
It seems to me that the current consensus for Force Layouts and the
like is to simply drop out of React for those components and let d3 do
its thing. This isn't ideal but it's way more performant.
What is the impact on React from letting D3 take care of rendering? Will it only impact the performance of the component using D3, or other components as well? Will direct manipulation of the DOM using D3 screw with React's virtual DOM in some way for example? I'm basically trying to get an idea of the price you have to pay for using D3.
I've worked on a project (private, unfortunately) where I used D3 to represent a UML editor. Everything used SVG manipulation to draw an SVG representing the UML.
The Editor UI logic was implemented in a unique React element (UMLEditor), using TypeScript and D3. You could pass the editor properties to set changes in the UML, and callbacks to get back the data. For instance, you can drag and drop a UML class (in 60fps), but the UI only triggers two events (drag, and drop) to React callbacks.
The key is to have the logic and events separated from the UI manipulation, and have a small amount of big react elements, and not so many small elements.
It could manage a UML with around 4K classes in 30fps.
Edit: Let's define a small application.
You have small react components with its children, like the root App element, a Navigation bar, a viewport, etc...
Every element but the UMLEditor have a small impact on the performance. UMLEditor element is a complex element without any React children. Every UI element inside it is rendered using D3. The real DOM of UMLEditor contains a complex SVG element managed entirely using D3.
To make this element interact with React, we pass as props callbacks for events like drag, drop, create new UML class... and one JavaScript class with all the D3 render logic.
We don't pass as prop the entire UML configuration, as it would have a negative impact on the performance. Instead, when we needed it for exporting purposes, the JavaScript class passed as a prop can give the whole UML configuration using a method.

How to preserve a component's instance while moving it to another parent component in react?

Suppose we have two sibling react components called OldContainer and NewContainer. There is a child component inside OldContainer that contains a <video> tag, and the video is currently playing.
The user can now drag the child component (with the video) and drop it in the NewContainer, and they expect the video to keep playing while it's being dragged and after being dropped.
So the video appears to stick to the mouse position, and when dragged and dropped in the new container, it animates to its new position (again, it doesn't get paused).
How would you implement this? Can we implement this in a pure way (in line with the spirit of pure functions)?
Clarification: I could have used some other element instead of a video tag for explaining this problem. A NumberEasing element would be a better example, since it would require the props and state of the component to be preserved during and after the interaction.
Update 1: Code examples obviously would be nice, but what I'm mainly looking for is just a general description of how you would approach this problem in a "functional" way. How do you keep your view code simple and easy to reason about? Who handles the drag-and-drop gesture? How do you model the data that's fed into the views?
Take a look at this library : react-reverse-portal
What is it that you want to preserve? Is it Javascript objects that the component holds as state, or is it state in the DOM (like how long a video has played, or text selection in an input box)?
If it's just Javascript objects as state, you're better of moving the source of that state to another service (something like Flux). That way, it doesn't matter if the component gets recreated because it can be recreated with the state that was there before.
EDIT
The way to keep your view code simple and easy to reason about is to not keep state inside your components. Instead, all data that the component needs should be passed into the component as props. That way, the component is "pure" in that it renders the same output given the same props. That also makes the problem of wanting to reuse a component instance a non-issue, since it doesn't matter when the same input gives the same output.
For drag and drop, I'd suggest looking at: https://github.com/gaearon/react-dnd.
How you model the data you pass to view components is up to you and the needs of your application. The components shouldn't care, they should just expect to get data passed as props, and to render them. But the popular approach to dealing with this is of course Flux, and there are many libraries that implements Flux in different ways.
SECOND EDIT
Regarding if you have a subtree with hundreds of components that you want to move: I'd still start off by making the state external (pure components), and render that tree in a new place. That means that React will probably recreate that entire subtree, which is fine. I wouldn't deviate from that path unless the performance of it turned out to be horrible (just guessing that it might be horrible isn't enough).
If the performance turned out to be horrible, I would wrap that entire subtree in a component that caches the actual DOM tree and reuses it (if it gets passed the same props). But you should only do this when absolutely needed, since it goes against what React tries to do for you.
THIRD EDIT
About gestures: I'd start out with listening to gesture events in componentDidMount, and in the event callback call setState on the component with the coordinates it should have. And then render the component in render with the coordinates given. React won't recreate the component when you call setState but it will re-render it (and diff the output). If the only thing you changed was the coordinates, it should render fast enough.
If that turns out to be too slow, like if the subtree of that component is huge and it becomes a bottleneck to recreate the subtree of vDOM, I'd reposition the DOM node directly in a RAF-loop outside of Reacts control. And I'd also put a huge comment on why that was needed, because it might seem wierd for some other developer later.
Create a new variable using const or var. Put the instance of data using rest spread operator, update the necessary data to pass and send the data to the component without mutating the state of component.
Just like:
const data = {
...this.state.child,
new_data : 'abc'
}

AngularJs multi level data drilling

I'm kind of a newbie in AngularJs and I have a complex JSON that i need to get data from to a auto complete.
I need to create an auto complete for ONLY the child elements in the the stucture without showing the parent categories.
Getting to the parents is easy, data[2].JobCategories and binding that to the ng-repeat and binding "jobParentCategoryModel.JobCategoryName" to the model does the trick.
But drilling to get only the children confuses me in the angular way. The way i see it, what I need to so is to to get only the children from the factory in new array of categories children and work with that. But for some reason in my mind it seem wrong to drill in the factory... Don't know why, just doesn't seem the angular way to do things.
PS. When looking at examples i saw lots of nested ng-repeat examples but i don't want to create the extra parent DOM elements for each child, so using nested repeats seams over head. But again I don't want to destroy the data structure (It is not two way binding so I don't know if it matter if i change the model at all).
What is the best practice to do this kind of deep drill down in angular?
I assume that you want to use only the child elements for instance in an ng-repeat but you do not want to create a separate data structure, that holds only these elements, in your scope. In this case I would write a function that extracts the elements and refer to this function in the ng-repeat:
<li ng-repeat="eachElement in getChildElements()">...</li>
This way you avoid redundancy and inconsistencies since your list automatically adapts to changes in the data structure.

Categories

Resources