How do I append D3 elements onto React components? - reactjs

I currently have a React page with multiple images that are based on an array of minutes that make up a total time period: [15, 10, 15, 5]. The images depict a bar graph, that shows the current period in light blue and the previous periods in dark blue:
Currently the images are hard coded but I am trying to use D3 to dynamically generate them. I can do it in a unit using SVG but when I try to insert it into React it's giving me problems. Each image needs the overall minute array to show the correct information. I have the array in a props variable at the high level of the page component. I have tried to create a component based on the D3 component I programmed but I can't figure out how to append SVG elements in React. Before, I could append an "svg" onto "body" but I can't do that in React.
I've tried to follow this guide:
https://react-d3-library.github.io
I have my D3 component in a file called ChunkGraph.js.
But in that react-d3-library guide it imports node (a DOM element) from the D3 file, which gives me a compile error when I try it.
EDIT: Figured it out... for anyone who comes after and needs to know... useRef is the key here, to form a dynamic link between react and your d3 element. react-d3-library isn't needed.

Related

How does chart updating works within the context of react?

I currently have a Radar chart in chart.js using the react integration.
I was suprised to note that, when I updated the data, instead of showing a completely new plot, it just transitioned smoothly from the previous dataset to the new one.
What I am interested in is to understand how it works under the hood, which honestly I can't understand, at least from looking at the code.
First: my understanding of React is that, when a prop or state changes, it computes the new DOM, and then merges the new DOM and the current DOM, applying only the difference between the two. However, chartjs seem to be implemented as a Canvas element.
The chartjs integration with react does not do much. Taking the Radar plot, this is what it does
export const Radar = /* #__PURE__ */ createTypedChart('radar', RadarController);
which is nothing but declare a <Chart> element and leave it to ChartJS to plot it. In fact, in ChartJS, we have this code, which basically manages the Canvas element and it is smart to perform transitions using animations and so on. This I understand (relatively): a lot of animation and transition helper functions, but this makes sense to me. However, this part is pure JavaScript. There's nothing that is aware of React.
What does not make sense is therefore how the react synchronization system is integrated with this JavaScript library so that the state invalidation of the props/state is synchronised to an animation, instead of a complete rewrite of the Canvas element. I don't seem to find where this magic happens in react-chartjs-2.
As you explained the canvas element does not get changed so it gets reused. To animate the chart chart.js itself has an update method. React-chartjs-2 uses a useeffect function that checks if the data you pass it has changed. If this is the case it calls the update function from chart.js itself and they handle the animations and updates itself:
useEffect(() => {
if (!chartRef.current) return;
if (redraw) {
destroyChart();
setTimeout(renderChart);
} else {
chartRef.current.update();
}
}, [redraw, options, data.labels, data.datasets]);
https://github.com/reactchartjs/react-chartjs-2/blob/4a010540ac01b1e4b299705ddd93f412df4875d1/src/chart.tsx#L78-L87
This is my understanding of the whole process after diving into the code base quite a bit. I've tried to be as detailed as possible with links to the exact line of code I am talking about. Hope this helps:
Beginning with the code snippet you shared:
export const Radar = /* #__PURE__ */ createTypedChart('radar', RadarController);
If you follow the RadarController via the import statement, you see that it is fetched from chart.js
Now we move to the Chart.js code and look for this controller RadarController. It is found in a file called src/controllers/controller.radar.js.
Within that file, you see an update function
This function then calls updateElements with the points information
This function gets the new point position which is then set in properties and passed into the updateElement function
This updateElement function directly takes us to the core.datasetController
Here you see a condition to check if the chart is in directUpdateMode. If not, it calls a function to _resolveAnimations
Within this function, you will see the new Animations(args) object
This eventually brings us to the core.animations file which consists of all the animation related information and processing.
One interesting bit I found here was: this is what seems to be making the beautiful movement of points to the changed location.
You can explore this Animations class further for more detailed understanding
So yeah essentially, it is the js part under the hood that facilitates the smooth transitions and this is how it does it. React code is essentially just like a wrapper of Chart.js calling this update method with the new values.
You can see here: https://github.com/reactchartjs/react-chartjs-2/blob/master/src/chart.tsx
The react-chartjs-2 library creates a component that adds a canvas and when the props update the component creates/updates an internal Chart object that uses the rendered canvas.
From what I saw the animation starts when the props are changed.
The path is props->react-chartjs-2 component->chart object->animation

Difficulties rendering 3D avatar with react-three-fiber and React

I'm trying to render a 3D avatar using react-three-fiber and React, but I'm experiencing some difficulties with positioning the avatar. As you can see from from the following CodeSandbox https://codesandbox.io/s/vigorous-ardinghelli-ypwjsb?file=/pages/index.js, the top of the avatar's head is not visible when you first render the page. However, if you change the position of the model (e.g. from [0.025, -0.9, 1] to [0.025, -1, 1]) and re-render the page, suddenly the avatar is showing correctly. Why is that?
Reposting the solution I got from a Reddit user:
it looks like the keyframe track actions["Armature|mixamo.com|Layer0"].play() pushes the model up and down.
i reexported the model
npx gltfjsx model.glb --keepnames
https://codesandbox.io/s/interesting-lewin-rnq66m?file=/pages/index.js and that seems to do it. it should preserve names by default when animations are present, i don't get why it's omitting them. but either way, it works.
should be fixed upstream (gltfjsx) as well now. another export should include names

Locate react elements inside shadowroot using typescript and Protractor [

Im trying to locate elements that are inside 9-11 shadow root. Regular locators such as xpath,css,id are not able to locate. I was able to locate element using JavascriptExecutor() in java. But the process is very tedious. Also im working on protractor framework with typescript.
I need to locate the element highlighted.
Any help is much appreciated!![enter image description here][1]
Instead of using custom javascript to find your elements, I would recommend the 'by.react' component, this makes react selection so much easier.
https://www.npmjs.com/package/protractor-react-selector
// with only component. If you don't provide any root element, it assume that root is set to '#root'
const myElement = element(by.react('MyComponent'));
// to fetch all elements matched with component, props and state, you can use protractor native 'all' method
const myElement = element.all(by.react('MyComponent'));
Let me know if this helps you :)

React avoidable re-rendering problem with AntDesign and PrimeReact

We are developing a huge application with React. One of our forms includes 60+ plus components placed on different Tab items.
When i try to edit an input it took 190ms to see typed chars in the textbox. After digging the problem for hours we realized adding a component increases the response time. Then we decided that the problem is antdesign s render logic. Then we tried it with PrimeReact using "why-did-you-update" package. The result was same!
When any change occurred in the state, all the components ( including Icons :) ) tried to render per "why-did-you-update" messages.
Here is the sandbox : https://codesandbox.io/s/6w30ro2l9w
Are the "why-did-you-update" messages wrong or we missing something?

Load static svg file in react and add dynamic styling

I am trying to load an SVG containing a map of country regions and then dynamically colorize the paths based on other data in the render function.
Is there a way in react to load a static SVG file at build or runtime and modify styles dynamically when rendering based on properties passed in?
You can use https://www.npmjs.com/package/react-samy-svg . This is how you can load an svg file and change an attribute. (No need to paste the svg code into the jsx)
<Samy path="https://raw.githubusercontent.com/hugozap/react-samy-svg/master/examples/1.svg">
<Proxy select="#Star" fill="red"/>
</Samy>
A Proxy element will select an svg element (using CSS selectors) and forward all its props to the selected element as attributes.
There is nothing hard about it.
Loading SVG file - just use $.ajax call for the resource, with dataType: 'text'
Use dangerouslySetInnerHTML to put it anywhere.
Changing of colors really depends on the way your SVG is structured. Ideally you should be able to change colors just using CSS (e.g. swap classes or generate style dynamically). If everything else fails, SVG is just text so you can do any text processing (color replacement) between steps 1 and 2.
I think it would be quite tough if even possible.
There are some approaches that claim to solve similar problem of converting string to react components (react-jsx-parser, html-to-react), or alternatively you can try converting html -> JSX -> JS (last step using babel) and subsequently requiring resulting js to obtain generated component.
Taking into account complexity of the steps above it might be simpler just to render SVG as html content of some div (using dangerouslySetInnerHTML) and later modify its styles using JS/jquery directly.

Resources