Highcharts with React Legend placement and more - reactjs

so I've recently introduced myself to Highcharts and I did create a hardcoded dummy chart on my app. However I'm having issues with mainpulating the placement specifically of the LEGEND circles. So here's the Link i drew code+inspiration from :
https://github.com/whawker/react-jsx-highcharts/blob/gh-pages/examples/Combo/App.js
And here's some of my code :)
render() {
const pieData = [
{
name: "Jane",
y: 17
},
{
name: "John",
y: 13
},
{
name: "Joe",
y: 20
},
{
name: "Ivan",
y: 50
}
];
return (
<HighchartsChart>
<Legend />
<YAxis id="number">
<PieSeries
id="total-consumption"
name="Total consumption"
data={pieData}
center={[300, 120]}
size={255}
showInLegend
/>
</YAxis>
</HighchartsChart>
);
so basically yeah I need the legend to move from the bottom to the right side etc , oh and as well as I'm not sure how to manipulate/display the values instead of the names on the chart itself .
Thanks in advance for ANY feedback and tips,
Yours truly ,
Victor (a confused Intern still)

As far as I can see from the examples of the react-jsx-highcharts library you are using the <Legend> component has some props that allow positioning.
To e.g. align it on the right try this:
<Legend layout="vertical" align="right" verticalAlign="middle" />
The documentation seems to be more than incomplete so your best chance is to look into the examples or dig into the source yourself to see which props might help you.
In most cases the components seem to be passing configuration options given as props to Highcharts as they are:
The intention of this library is to provide a very thin abstraction of Highcharts using React components. This has been achieved by passing Highcharts configuration options as component props.
In the vast majority of cases, the name of the configuration option, and the name of the component prop are the same.

Related

Get a list of components and their props from MDX string - by regex?

My problem - Get components & props from MDX/JSX string
I have an MDX string with Front-matter meta data in YAML, some regular text, some markdown and some React components.
I need to get the list of all React (non-HTML) components from it with their parameters.
So given this example:
---
title: Title of documents
tags: one, two, three
---
# My heading H1
Some text in paragraph. Than the list:
- First item
- Second item
More text with [a link](https://example.com).
<Articles category="theatre" count={3} />
Further text with more information.
<Newsletter categories={['theatre', 'design']} />
<MultilineComponent
paramA="A"
paramB="B"
/>
<ComponentWithChildren param="value">
Some children
</ComponentWithChildren>
... I would need this output:
[
{
component: 'Articles',
props: {
category: 'theatre',
count: 3,
},
},
{
component: 'Newsletter',
props: {
categories: ['theatre', 'design'],
}
},
{
component: 'MultilineComponent',
props: {
paramA: 'A',
paramB: 'B',
}
},
{
component: 'ComponentWithChildren',
props: {
param: 'value',
}
}
]
Also I need to do this on the server, so I don't have access to browser functionality (window, document, etc.).
What I've tried
Some basic Regex, but as I'm far from being professional in regexing, now I have two problems. :)
Is there some built in way how to parse JSX string to get a list of components & props in the way that I've described above? Or is there some maybe some other parser that I can use to solve this? If not, is there some Regex pattern I can use to get this?
Quick summary on "Why"
During the build of my Next.js project I need to determine which data is actually needed for each MDX page in the bundle. So if I see this in the Mdx file:
...other text
<Articles category="theatre" count={3} />
...other text
... which I'm somehow able to parse to this:
component: "Articles"
category: "theatre"
count: 3
that's enough info for me to know that I need to send those data to the page:
[
{
title: 'Romeo and Juliet',
category: 'theatre',
},
{
title: 'The Cherry Orchard',
category: 'theatre',
},
{
title: 'Death of a Salesman',
category: 'theatre',
}
]
Would you be able to help me with this? Thank you in advance! 💪
Edit
#Rango's answer pointed me to the right direction! One caveat: jsx-parser can not handle multiline components to which Rango's proposed the following solution:
if (rsp.test(c)) continue; // add before /index.js:374
This however removes all whitespace from string attributes. So I've replaced it with this:
if (/[\n\r]/.test(c)) continue; // this should remove lines only
So far this solution works. I would be more comfortable to use more stable libraries, but unfortunately none of the proposed solution worked for me (acorn-jsx, react-jsx-parser, babel/parser).
Not sure that parsing JSX with regular expressions is efficient because curly brackets {...} can contain any JS expression, so if you choose this way then prepare to parse Javascript as well.
Fortunately, there are a bunch of JSX parsers that can do it for you. E.g. the first one I picked was jsx-parser and this small beast can parse your example (with a simple trick). The shape of the result is quite different but you can transform it to match your needs.
var test = `
---
title: Title of documents
tags: one, two, three
---
# My heading H1
Some text in paragraph. Than the list:
- First item
- Second item
More text with [a link](https://example.com).
<Articles category="theatre" count={3} />
Further text with more information.
<Newsletter categories={['theatre', 'design']} />
<MultilineComponent
paramA="A"
paramB="B"
/>
<ComponentWithChildren param="value">
Some children
</ComponentWithChildren>
`
const components = [...test.matchAll(/<[A-Z]/g)]
.map(match => JSXParser(test.slice(match.index)))
document.getElementById('result').textContent = JSON.stringify(components, null, 2)
<script src="https://unpkg.com/jsx-parser#1.0.8/index.umd.js"></script>
<pre id="result">Hello</pre>
In my snippet I used UMD version of the package, but for node.js consider choosing ES module ofc.

How to create a dynamic layout in react with fully configurable JSON data

I am writing a react application. A core requirement is that the application be completely dynamic and configurable, including choosing layouts, sections and fields, validation etc.
I have two UI. One is the config UI where the user can select the layout, sections, fields like what type of html component etc. Once this is saved, I get data as JSON where I need to draw the UI. This is my second UI. My concern is how do I structure the components to render the UI with the JSON data. The fields & sections will be same but the layout will be different based on what is been selected in the config UI. Below is the rough JSON schema.
{
title: "Test title",
layout: [
{
name: "layout-a"
},
sectionA: {
name: "breadcrumbs"
field: [
{
name: "test",
value: "test",
type: "text"
}
]
},
sectionB: {
name: "actions"
field: [
{
name: "Create",
value: "Create",
type: "button"
}
]
}
]
}
I was thinking of having a layout component which renders all the children from the JSON. Component looks like below
const Layout = ({ children }) => {
return (
<div>
<div className="container">
<div className="content">{children}</div>
</div>
</div>
);
};
and top level component where we read the config json and based on the layout render the component
<Layout>
{viewToShow === "layoutA" && <LayoutA data={config.sections} />}
{viewToShow === "layoutB" && <LayoutB data={config.sections} />}
</Layout>
My question is how do I construct the LayoutA, B or C component so that these sections and fields are rendered differently on the UI?
I think your question leaves a lot of unspecified points for us to offer you a proper solution. My advice is to investigate better what the project real needs are and its main goals, then lay out each piece (component) thoroughly checking what should be "configurable" and to which extent, before coming up with any implementation.
Taking your example "as is", my first thought is to wrap your App component into a Context provider, similar to what we'd do to manage themes.
export const layouts = {
layoutA: {
background: '#fff',
sectionWidth: '100%',
},
layoutB: {
background: '#000',
sectionWidth: '50%',
},
};
export const LayoutContext = React.createContext({
layout: layouts.layoutA, // default layout
toggleLayout: () => {},
})
You could then further populate the layouts object with metadata from a database. Supposing changes do not originate from the UI (think Webflow or Wix Editor), you could use a CMS to update the metadata and propagate the changes.
An example usage would be:
function LayoutTogglerButton() {
return (
<LayoutContext.Consumer>
{({ layout, toggleLayout }) => (
<button
onClick={toggleLayout}
style={{ backgroundColor: layout.background }}>
Toggle Layout
</button>
)}
</LayoutContext.Consumer>
)
}
Again, there are a lot of unspecified points on your request for us to be more specific. The request for "an application to be completely dynamic and configurable, including choosing layouts, sections and fields, validation etc" could mean many things.
Examples of more specific questions: How to create dynamic forms in React with functional components? How to create drag and drop dashboard widgets with React? How to live update/customise themes with styled-components?
Perhaps you could be more specific? Cheers
I am researching a possibility to do something similar. An off the bat approach would look somewhat like this: https://codesandbox.io/s/still-sun-cecudh?file=/src/App.js
Then of course, where this the layout object will be generated and where the parsing will take place will dependent on your use case. I am going with context for layout object generation and a dedicated component for object tree traversal.

Use images instead of svg circle (react-d3-tree)

I recently updated to version 2.0.1 and I am struggling to set images instead of svg circles to individual nodes. In the older versions I used nodeSvgShape property:
nodeSvgShape: {
shape: 'image',
shapeProps: {
href: AppState.config.api.img + mainTile.image,
width: 100,
height: 100,
x: -50,
y: -17,
},
},
However in the current version this does nothing. Is there any way how can I achieve this in the current version?
Thank you in advance
If you are still having this issue after a year, here is how I did this.
I was able to do this with other SVG images by using the renderCustomNodeElement properties of the Tree component. By passing a render function that you create, you are able to apply the render function to each node (found on the docs here: https://www.npmjs.com/package/react-d3-tree#styling-nodes ).
Below is an example of how to implement it, say using an object that maps the name of the node to an SVG string and then passing that to the Tree component:
import SVG from 'react-inlinesvg';
const renderMol = ({ nodeDatum, toggleNode }) => (
<g>
<SVG src={svgMapping[nodeDatum.name]}/>
</g>
);
return (
<Tree data={mydata}
renderCustomNodeElement={nameOrMol} />
)

React Calendly Package infinitely loading

I am currently using the react-calendly package and everything is working as expected. I am able to pick a date, etc. and post the event to the calendar. The only issue is below the calendar there are 3 gray dots showing the widget is loading. They never go away, the widget appears to be in a constant state of loading. Is there a reason this is happening? Or maybe could offer a separate solution as opposed to the package I am using. Click https://m44fc.csb.app/ to see what I am talking about. Here is the code pen if you would like to test a solution https://codesandbox.io/s/dreamy-dewdney-m44fc?file=/src/App.js
My code is as follows:
import React, { useState } from 'react'
import { InlineWidget } from 'react-calendly'
function App() {
return (
<>
<InlineWidget
url='https://calendly.com/myURL'
utm={{
utmCampaign: 'Spring Sale 2019',
utmContent: 'Shoe and Shirts',
utmMedium: 'Ad',
utmSource: 'Facebook',
utmTerm: 'Spring'
}}
/>
</>
)
}
export default App
getting the following issue in my chrome dev tools:
Resolve this issue by updating the attributes of the cookie:
Specify SameSite=None and Secure if the cookie is intended to be set in cross-site contexts. Note that only cookies sent over HTTPS may use the Secure attribute.
Specify SameSite=Strict or SameSite=Lax if the cookie should not be set by cross-site requests
Is there something I need to do to resolve these?
Looks like the React component is missing an important style property. We'll look into patching it, but in the meantime the workaround is to pass the following styles yourself when you're using the component:
<InlineWidget
url="https://calendly.com/robert-612/complimentary-consultation"
utm={{
utmCampaign: "Spring Sale 2019",
utmContent: "Shoe and Shirts",
utmMedium: "Ad",
utmSource: "Facebook",
utmTerm: "Spring"
}}
styles={{
minWidth: "320px",
height: '630px',
position: 'relative',
}}
/>
The minWidth and height values are taken from the component's defaults, the position: relative is what was missing. This should ensure that the widget always covers the loading dots, no matter what the page size is.

Can I rearrange passed data in a presentational component

Your answers have highlighted an oversight on my part. I was taking this pattern container/presentational way too seriously and this made me realize that we could do without <Component />.
Say I have two components, <ComponentContainer /> and <Component /> and the latter renders a <Table /> component. For the sake of an example, I use Table from Ant Design.
Now, <Table /> is expecting a property dataSource with the following shape:
const dataSource = [
{
key: '1',
name: 'Mike',
age: 32,
address: '10 Downing Street',
},
{
key: '2',
name: 'John',
age: 42,
address: '10 Downing Street',
},
];
Where should I initialize this variable? Do I have to set it in ComponentContainer and pass it down to <Component /> which just passes it further down to <Table> I initially passed down some unformatted data to <Component />, say (note: the shape might also be something completely different):
const data = {
{
name: 'Mike',
age: 32,
address: '10 Downing Street',
},
{
name: 'John',
age: 42,
address: '10 Downing Street',
}
}
and then declared and set that dataSource variable in <Component /> using this data:
const { data = [] } = props
const dataSource = data.map((pieceOfData, i) = > ({
...pieceOfData,
key: i
}))
<ComponentContainer > is not supposed to know that <Component /> is using a <Table /> so for me, it was ok to pass down some unformatted data to shape it then as needed further down the component tree even though we are in a presentational component. But I was told otherwise so I don't know. Is it really bad to do anything else than rendering?
This is known as prop-drilling, a process you go through to pass your data down in the React component tree. While it's not a bad pattern, there are some issues when trying to use it from such top-level components. Usually we want to keep logical pieces together and a clear distinction between presentational and logical components.
If you want to read more about it, I highly suggest Kent C. Dodds text on prop-drilling. The text has the potential issues and how to go around it, like using state management or React's Context API.
I recommend reading the beginning of this article by Dan Abramov https://medium.com/#dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0
It used to be that everyone lived and died by the presentational and container component idea and prop drilling. I tend to disagree with that model. I believe that the component logic and information should live as close as possible to where it's being used. It makes it easier for me to read and understand what code is doing if I don't have to constantly check back up 2 files to see what is being passed down. As stated in the other answer by Inacio there are good ways around this issue especially with the use of hooks.

Resources