Resize highcharts using react-grid-layout not working - reactjs

I am working in react and using highcharts with react-grid-layout to resize the elements in div. Somehow resizable feature is working for images but not with highchart. Grid.js is a file that makes ResponsiveReactGridLayout and it gets the highchart from chart.js file. Please find the code below.
//Grid.js
import React, { Component } from 'react';
import {Responsive, WidthProvider,ReactGridLayout} from 'react-grid-layout';
import Charts from './charts.js';
const ResponsiveReactGridLayout = WidthProvider(Responsive);
class Grid extends Component {
onLayoutChange(layout) {
console.log(layout);
}
render(){
return (<div style={{borderStyle: 'groove'}}>
<h2> Panel Header </h2>
<ResponsiveReactGridLayout className="layout"
breakpoints={{lg: 1200, md: 96, sm: 768}}
cols={{lg: 5, md: 10, sm: 6}}
onLayoutChange={this.onLayoutChange}>
<div key="c" data-grid={{x: 0, y: 0, w: 1, h: 3}} style={{ border:'1px solid green', borderStyle: 'groove'}}>
<img src="https://cdn.geckoandfly.com/wp-content/uploads/2013/03/530-smiley-face.jpg" style={{width:'inherit', height:'inherit'}} />
</div>
<div key="d" className = 'react-grid-item react-resizable'
data-grid={{x: 1, y: 0, w: 1, h: 3}} style={{ border:'1px solid green', borderStyle: 'groove'}}
>
<Charts style={{width:'inherit'}} id={'Chart 1'}/>
</div>
<div key="e" data-grid={{x: 2, y: 0, w: 1, h: 3}} style={{ border:'1px solid green',borderStyle: 'groove'}}>
<Charts style={{width:'inherit'}} id={'Chart 2'}/>
</div>
<div key="f" data-grid={{x: 3, y: 0, w: 1, h: 3}} style={{ border:'1px solid green',borderStyle: 'groove'}}>
<Charts style={{width:'inherit'}} id={'Chart 3'}/>
</div>
</ResponsiveReactGridLayout>
</div>
)
}
}
export default (Grid);
//Charts.js
import React, { Component } from 'react';
const Highcharts = require('highcharts');
class Charts extends Component{
constructor(props){
super(props);
this.state = {
data : {
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
series: [{
data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 295.6, 454.4]
}]
},
pieData: [{name: "Firefox",y: 6},{name: "MSIE",y: 4},{name: "Safari",y: 4},{name: "Opera",y: 1},{name: "Chrome",y: 7}]
};
}
/**
* Inject highcharts markup into the DOM after the rest of the component has mounted
* #return {None}
*/
componentDidMount() {
// Load in any highcharts modules
if (this.props.modules) {
this.props.module.forEach((module) => {
module(Highcharts);
});
}
// Create the actual chart and assign reference
const props = this.processPropsModel(this.props);
const containerRef = `container${props.id}`;
this.chart = new Highcharts.chart(
containerRef,
props.options
);
}
processPropsModel(props) {
const newProps = {};
newProps.id = this.props.id;
newProps.options = this.generateDefaultOptions();
return newProps;
}
/**
* Generating some default chart options for placeholding purposes
* #return {Object} The options to be passed into the chart
*/
generateDefaultOptions() {
return {
title: {
text: this.props.id,
x: -20 //center
},
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
yAxis: {
title: {
text: null
}
},
tooltip: {
valueSuffix: '°C'
},
series: [{
name: 'Tokyo',
data: [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6]
}]
};
}
render(){
const props = this.processPropsModel(this.props);
return (
<div id={`container${props.id}`}>
</div>
);
}
}
export default Charts;

So, I was struggling with the same issue using highcharts-react-official and react-grid-layout.
Here is how I finally got it working.
tl;dr
Give height 100% to all of your chart's parents up to the grid item.
There is an annoying div that highcharts creates by himself. Find a way to identify it and give it height 100%.
Give height 100% to the chart itself.
Use the react highcharts callback to get your chart object.
When your component updates reflow your chart.
Below is my responsive grid layout, just to give some context.
// Component/Grid/Grid.js
<ResponsiveGridLayout
...
>
{this.state.widgets.map((widget) =>
<Card key={widget.DWG_ID}>
<Widget
widget={widget}
/>
</Card>
)}
</ResponsiveGridLayout>
Now, inside the Widget Component, set the height of any div that will be a parent of your highchart to 100%.
// Component/Widget/Widget.js
<CardBody className="widgetContent">
<CardTitle className="widget-title">{this.props.widget.DWG_LABEL}</CardTitle>
<Chart
widget={this.props.widget}
/>}
</CardBody>
For the jsx above I only needed to do this for the element CardBody with class widgetContent, so
// Component/Widget/Widget.css
.widgetContent { height: 100%; }
Now, in the chart component (where all the fun was), I had to create a very ugly div just to be able to identify the outer-most div that highcharts creates.
elements created by highcharts
The infamous div in question can be seen in the image above, right under the div with class highchartsWrapper, with the property data-highcharts-chart .
This div was the only parent of my chart that I could not identify directly to give 100% height. So I created the wrapper to be able to identify it unequivocally.
Note that in the chart options we passed a class name as well, to be able to give the chart itself the css height property.
If anybody has a neater idea of how to identify this problematic div please let me know.
// Component/Chart/Chart.js
options = {
...
chart: { className: 'chart' }
}
<div className="highchartsWrapper">
<HighchartsReact
highcharts={Highcharts}
options={options}
callback={(chart) => this.setChart(chart)}
/>
</div>
So I could give it the css
// Component/Chart/Chart.css
.highchartsWrapper > div {
height: 100%;
}
.chart {
height: 100%;
}
Now your highchart would ideally assume the correct width and height. But there was another complication: when the highchart renders for the first time and checks his parent's height, react-grid-layout isn't yet done with his resizing magic. This means your chart will be teeny-tiny. Moreover, when you resize your grid items you want your highchart to resize to its new parent size. But wait, I've worked with highcharts before, I know how to do this! The good old chart.reflow() ! Unfortunately this ended up not being that easy.
To start with, just getting the chart object on which I can call reflow wasn't very straightforward. If you notice, I gave my HighchartsReact a callback
(chart) => this.setChart(chart)
This is just to store the chart object as a property of my class component. My setChart function does only the following:
setChart(chart) {
this.chart = chart;
}
It might seem stupid to do it like this. Why not just give setChart directly to the callback property of HighchartsReact? Well because if you do, as per the highcharts-react-official documentation, your this inside the setChart function would be your chart object... All very confusing, but it seems to work like this.
Again, if somebody has a neater solution, let me know
Finally, we can call our this.chart.reflow() when our Chart Component is updated. what I did was something like
constructor() {
super(props)
this.firstResize = true;
}
componentDidUpdate(prevProps) {
if (this.didWidgetSizeChange(prevProps) || this.isFirstResize) {
this.chart.reflow();
this.isFirstResize = false;
}
}
When the component updates we call the chart reflow. On the componentDidMount the grid item doesn't have his final size yet, so I used a flag to figure out the first update (that would be exactly that: grid item has finished first resize). Then for any other update I wrote a function that basically compares the previous layout for this grid item with the new to decide if the size or width have changed. If so, we reflow again to resize the highcharts to the new grid item size.
Hope this helps!
Peace!

Here is the sample solution to make it fit in the Grid....
import React from 'react';
import './App.css';
import '/node_modules/react-grid-layout/css/styles.css';
import '/node_modules/react-resizable/css/styles.css';
import GridLayout from 'react-grid-layout';
import Highcharts from "highcharts/highstock";
import HighchartsReact from "highcharts-react-official";
const options = {
series: [
{
data: [1, 2, 3]
}
]
};
class MyFirstGrid extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
this.conRef = React.createRef();
}
render() {
// layout is an array of objects, see the demo for more complete usage
var layout = [
{ i: "a", x: 0, y: 0, w: 5, h: 5 },
{ i: "b", x: 1, y: 0, w: 3, h: 2 },
{ i: "c", x: 4, y: 0, w: 1, h: 2 }
];
return (
<GridLayout
className="layout"
layout={layout}
cols={12}
rowHeight={30}
width={1200}
onResizeStop={function(event) {
this.myRef.current.chart.setSize(this.conRef.current.clientWidth,this.conRef.current.clientHeight)
console.log('hello', event);
}.bind(this)}
>
<div ref={this.conRef} style={{ backgroundColor: "#00000000" }} key="a">
<HighchartsReact
ref= {this.myRef}
containerProps={{ style: { width: '100%', height: '100%' } }}
options={options}
highcharts={Highcharts}
/>
</div>
<div style={{ backgroundColor: "red" }} key="b">
b
</div>
<div style={{ backgroundColor: "blue" }} key="c">
c
</div>
</GridLayout>
);
}
}
export default MyFirstGrid;

I think the reason why the functionality of resizing highchrts is not working you can find it from the documentation of 'reflow' from hightcharts
By default, the chart reflows automatically to its container following a window.resize event, as per the chart.reflow option. However, there are no reliable events for div resize, so if the container is resized without a window resize event, this must be called explicitly.
The situation matches what you did now: you tried to resize the div itself but not the window size, so it doesn't work as you expected.
What I did to make my charts resizable in grid as following:
Create a function to do reflow
const onLayoutChange = () => {
for (let i = 0; i < Highcharts.charts.length; i += 1) {
if (Highcharts.charts[i] !== undefined) {
Highcharts.charts[i].reflow(); // here is the magic to update charts' looking
}
}
};
Use onLayoutChange provided by react-grid-layout
<GridLayout
cols={12}
layout={layout}
rowHeight={30}
width={1200}
onLayoutChange={() => onLayoutChange()}
>
...
</GridLayout>
And then...BANG! you got resizable charts controlled by the resize button in react-grid-layout.
Make it easy to understand, you can view my playground here:
https://codesandbox.io/s/resize-highcharts-in-grid-9e625?file=/src/App.js

Related

Change color of slices of piechart in plotly.js using react-plotly.js

import Plotly from "plotly.js";
import createPlotlyComponent from "react-plotly.js/factory";
export const Plot = createPlotlyComponent(Plotly);
export function PieChart() {
return <Plot data={data} layout={layout} config={{ displaylogo: false }} useResizeHandler={true} style={{ width: '100%' }} />;
}
I want to change the color of Piechart slices, I referred to the documentation of plotly and added
marker: {
color: 'rgba(255,153,51,0.6)',
width: 1
}
too but it's not working
This is array,
maker.color --> maker.colors
You can do this as below
marker: {
colors: ['rgb(56, 75, 126)', 'rgb(18, 36, 37)', 'rgb(34, 53, 101)'],
width: 1
}
Here is DEMO for this,

Dynamically adjust ImageList columns based on screen size?

I've tried using ImageList component instead of Grid as I just need a grid of photos with titles and it seems to be the whole point of ImageList. My issue is that unlike with Grid I cannot pass breakpoint props for different screen sizes (which I find weird as this would seem logical) so that I can get different count of columns on different screens. What would be the best approach to adjust number of columns based on screen size?
ImageList uses CSS grid and needs the col prop to set the grid-template-columns but without any responsive API baked in. You can swap the ImageList with a Box component with the display set to grid, and uses the sx prop to declare the column template value depend on the screen size, but first let define some breakpoints:
const theme = createTheme({
breakpoints: {
values: {
mobile: 0,
bigMobile: 350,
tablet: 650,
desktop: 900
}
}
});
Then in the component, you can start using it like this:
import ImageListItem, { imageListItemClasses } from "#mui/material/ImageListItem";
<ThemeProvider theme={theme}>
<Box
sx={{
display: "grid",
gridTemplateColumns: {
mobile: "repeat(1, 1fr)",
bigMobile: "repeat(2, 1fr)",
tablet: "repeat(3, 1fr)",
desktop: "repeat(4, 1fr)"
}
// standard variant from here:
// https://github.com/mui-org/material-ui/blob/3e679ac9e368aeb170d564d206d59913ceca7062/packages/mui-material/src/ImageListItem/ImageListItem.js#L42-L43
[`& .${imageListItemClasses.root}`]: {
display: "flex",
flexDirection: "column"
}
}}
>
{itemData.map((item) => <ImageListItem {...}/>)}
</Box>
</ThemeProvider>
Live Demo
References
Media queries in MUI components
https://mui.com/customization/breakpoints/#main-content
I used the useMediaQuery hook to get the cols props for the ImageList component.
import { ImageList, ImageListItem, useMediaQuery } from '#mui/material';
function Gallery() {
const matches = useMediaQuery('(min-width:600px)');
return (
<ImageList cols={matches ? 3 : 2} variant="masonry">
<ImageListItem>
...
</ImageListItem>
</ImageList>
);
}
I spotted a similar problem. The ImageList renders a <ul> tag in DOM. Hence I created my own ImageList styled <ul> component which works fine with ImageListItem. Here as per the gridTemplateColumns attribute for screens with display size sm will show 2 images, display size md will show 4 images
and display size lg will show 5 images.
import * as React from 'react';
import ImageListItem from '#mui/material/ImageListItem';
import { styled } from '#mui/material/styles';
const ImageGalleryList = styled('ul')(({ theme }) => ({
display: 'grid',
padding: 0,
margin: theme.spacing(0, 4),
gap: 8,
[theme.breakpoints.up('sm')]: {
gridTemplateColumns: 'repeat(2, 1fr)'
},
[theme.breakpoints.up('md')]: {
gridTemplateColumns: 'repeat(4, 1fr)'
},
[theme.breakpoints.up('lg')]: {
gridTemplateColumns: 'repeat(5, 1fr)'
},
}));
export default function ImageGallery({imageData}) {
return (
<ImageGalleryList>
{itemData.map((item) => (
<ImageListItem key={item.img}>
// Replace this with your ImageListItem
</ImageListItem>
))}
</ImageGalleryList>
);
}
This solution I came up with works, but seems like a lot of lines for something that Grid handles out of the box. Doesn't ImageList have some built in responsive design implementation?
export function Example(props) {
// not sure if there is a way to get something like this dictionary from React?
const breakpoints = {
xs: 0,
sm: 600,
md: 960,
lg: 1280,
xl: 1920
}
const getColumns = (width) => {
if (width < breakpoints.sm) {
return 2
} else if (width < breakpoints.md) {
return 3
} else if (width < breakpoints.lg) {
return 6
} else if (width < breakpoints.xl) {
return 7
} else {
return 8
}
}
const [columns, setColumns] = useState(getColumns(window.innerWidth))
const updateDimensions = () => {
setColumns(getColumns(window.innerWidth))
}
useEffect(() => {
window.addEventListener("resize", updateDimensions);
return () => window.removeEventListener("resize", updateDimensions);
}, []);
return (
<ImageList cols={columns}>
{/* list items ... */}
</ImageList>
)
}
Instead of using ImageList I used "Image masonry" seems to work.
https://mui.com/material-ui/react-masonry/#main-content
<Masonry columns={{ xs: 1, sm: 2, md: 3, lg: 4, xl: 5 }} spacing={{ xs: 1, sm: 2 }}>
Image masonry
This example demonstrates the use of Masonry for images. Masonry orders its children by row. If you'd like to order images by column, check out ImageList.
I resolved this by overriding column-count property on ImageList (root component)
So, you can add breakpoints using sx props
<ImageList
sx={{
columnCount: {
xs: '1 !important',
sm: '2 !important',
md: '3 !important',
lg: '4 !important',
xl: '5 !important',
},
}}
>
{/* list items ... */}
</ImageList>

How can we animate the display of records using react-spring

How can we animate the display of records using react-spring. Can we call the useTransition in useEffect() ? I would like to animate records from bottom to top one by one when user navigate to the page. I have tried below nothing is happening..? Any advise would be really helpful.
https://codesandbox.io/s/inspiring-snowflake-34dpx?file=/src/App.js:711-881
import { useEffect, useState } from "react";
import { useTransition, animated } from "react-spring";
import "./styles.css";
const array1 = [
{ id: "1", name: "Cat" },
{ id: "2", name: "Dog" },
{ id: "3", name: "Cow" }
];
export default function App() {
const [list, setList] = useState(array1);
const height = 20;
useEffect(() => {
setList(array1);
}, []);
const transitions = useTransition(
Object.entries(list).map((data, i) => ({ ...data, y: i * height })),
{
from: { position: "absolute", opacity: 0 },
enter: { height: 0, opacity: 1 },
leave: { opacity: 0 },
config: { tension: 220, friction: 120 }
}
);
return (
<div className="App">
{/* {Object.entries(list).map((item, index) => (
<div key={item.id} className="record">
<span key={item.name}>{item.name}</span>
</div>
))} */}
{Object.entries(transitions).map(({ item, props, key }) => (
<animated.div key={key} style={{ ...props, position: "absolute" }}>
<div key={item.id} className="record">
<span key={item.name}>{item.name}</span>
</div>
</animated.div>
))}
</div>
);
}
The transitions variable is a function, so you don't want Object.entries(transitions).map(). It's not an error because functions in Javascript are also objects, but it's not going to do anything because the array of entries is an empty array.
You want to call the transitions function, which is its own sort of mapper.
{transitions((props, item, key) => (
Well now I'm seeing a cyan box instead of a white screen. So that's a little progress, but there's more to do.
If you console.log your item object you'll see that it doesn't look right.
Object.entries(list).map((data, i) => ({ ...data, y: i * height }))
You are mapping an array of object entries, so the data variable is an array containing the key and the value. You don't want that. list is already an array, so ditch the Object.entries.
list.map((data, i) => ({ ...data, y: i * height })),
Now I see "Cow"! But the other two are hidden because your items are appearing on top of each other.
You are using absolute positioning but you haven't passed the position down to the component. Since you aren't animating that value, it's a property of item rather than props.
<animated.div key={key} style={{ ...props, position: "absolute", top: item.y }}>
Now I see all three!
But the overlapping background blocks are probably not what you intended. I'm not sure what you intended, really, because you have a height of 20 in your JS and 100px in your CSS. You also have a height property in your animation but it's not doing anything.
All of your list items have height: 0px because you are setting the height to 0 in the enter property, which is called when an item first enters the list. On the other hand, the from property sets the initial values that the item animates away from, so maybe you want to have an initial value of height: 0 in from and some final value of height in enter.
You can animate the height of the background, but that won't impact the height of the text. You might want a transform like scaleY. You can use a transform instead of the height animation (all items start out in their final position and grow in place) or alongside the height animation (all items start together at the top and grow down).
Here's one possible effect: Code Sandbox Link
style.css
.App {
font-family: sans-serif;
text-align: center;
}
.record {
width: 300px;
background-color: aqua;
margin: 20px 0;
color: #1f1d1d;
}
.title {
font-size: 30px;
padding: 35px;
}
App.js
import { useState } from "react";
import { useTransition, animated } from "react-spring";
import "./styles.css";
const array1 = [
{ id: "1", name: "Cat" },
{ id: "2", name: "Dog" },
{ id: "3", name: "Cow" }
];
export default function App() {
const [list, setList] = useState(array1);
const transitions = useTransition(list, {
from: { opacity: 0, scaleY: 0 },
enter: { opacity: 1, scaleY: 1 },
leave: { opacity: 0 },
config: { tension: 220, friction: 120 }
});
return (
<div className="App">
{transitions((props, item, key) => {
console.log(props, item, key);
return (
<animated.div key={key} style={{ ...props }} className="record">
<div className="title">{item.name}</div>
</animated.div>
);
})}
</div>
);
}
Edit
As requested, from the bottom to the top one after another:
export default function App() {
const height = window.innerHeight;
const [list, setList] = useState(array1);
const transitions = useTransition(list, {
from: { opacity: 0, translateY: height },
enter: { opacity: 1, translateY: 0 },
leave: { opacity: 0 },
config: { tension: 220, friction: 120 },
trail: 200
});
return (
<div className="App">
{transitions((props, item, key) => {
console.log(props, item, key);
return (
<animated.div key={key} style={{ ...props }} className="record">
<div className="title">{item.name}</div>
</animated.div>
);
})}
</div>
);
}

Resize High Charts based on grid layout width and height using react

I have a wrote a grid layout component in react. Inside the grid, I have loaded the high chart and it works great. On resizing the width and height of the grid, the high chart doesn't resize and it breaks when resizing.
I have searched for stack overflow and found the same question in here "Resize highcharts using react-grid-layout not working". Then i came to know that chart reflow method is to be called to make the high chart fit with in the grid when the grid layout changes. Since i am new to react, I don't know how to make it possible. Help me with some solutions.
Here's the code i tried:
import React from 'react';
import logo from './logo.svg';
import './App.css';
import '/home/paulsteven/Documents/resize-ui/resize_ui/node_modules/react-grid-layout/css/styles.css';
import '/home/paulsteven/Documents/resize-ui/resize_ui/node_modules/react-resizable/css/styles.css';
import GridLayout from 'react-grid-layout';
import BarChart from "highcharts-react-official";
class MyFirstGrid extends React.Component {
state ={
options :{reflow:true,
title: {
text: 'Fruit Consumption'
},
subtitle: {
text: 'Steven Chart'
},
chart: {
type: 'bar'
},
xAxis: {
categories: ['Apples', 'Bananas', 'Oranges']
},
yAxis: {
title: {
text: 'Fruit eaten'
}
},
series: [{
name: 'Prince',
data: [4, 4, 2]
}, {
name: 'Syed',
data: [5, 3, 5]
},
{
name: 'Sam',
data: [1, 3, 3]
}]
}
}
render() {
// layout is an array of objects, see the demo for more complete usage
var layout = [
{i: 'a', x: 0, y: 0, w: 5, h: 2},
{i: 'b', x: 1, y: 0, w: 3, h: 2},
{i: 'c', x: 4, y: 0, w: 1, h: 2}
];
return (
<GridLayout className="layout" layout={layout} cols={12} rowHeight={30} width={1200}>
<div style={{backgroundColor: 'grey'}} key="a">
{/* <div id="container" style={{width:'100%',height:'400px'}}></div> */}
<BarChart options ={this.state.options} />
</div>
<div style={{backgroundColor: 'red'}}key="b">b</div>
<div style={{backgroundColor: 'blue'}} key="c">c</div>
</GridLayout>
)
}
}
export default MyFirstGrid;
I think the reason why the functionality of resizing highchrts is not working you can find it from the documentation of 'reflow' from hightcharts
By default, the chart reflows automatically to its container following a window.resize event, as per the chart.reflow option. However, there are no reliable events for div resize, so if the container is resized without a window resize event, this must be called explicitly.
The situation matches what you did now: you tried to resize the div itself but not the window size, so it doesn't work as you expected.
What I did to make my charts resizable in grid as following:
Create a function to do reflow
const onLayoutChange = () => {
for (let i = 0; i < Highcharts.charts.length; i += 1) {
if (Highcharts.charts[i] !== undefined) {
Highcharts.charts[i].reflow(); // here is the magic to update charts' looking
}
}
};
Use onLayoutChange provided by react-grid-layout
<GridLayout
cols={12}
layout={layout}
rowHeight={30}
width={1200}
onLayoutChange={() => onLayoutChange()}
>
...
</GridLayout>
And then...BANG! you got resizable charts controlled by the resize button in react-grid-layout.
Make it easy to understand, you can view live working here:
https://codesandbox.io/s/resize-highcharts-in-grid-9e625?file=/src/App.js
Here's the Solution to make it fit in the grid layout:
import React from 'react';
import './App.css';
import '/node_modules/react-grid-layout/css/styles.css';
import '/node_modules/react-resizable/css/styles.css';
import GridLayout from 'react-grid-layout';
import Highcharts from "highcharts/highstock";
import HighchartsReact from "highcharts-react-official";
const options = {
series: [
{
data: [1, 2, 3]
}
]
};
class MyFirstGrid extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
this.conRef = React.createRef();
}
render() {
// layout is an array of objects, see the demo for more complete usage
var layout = [
{ i: "a", x: 0, y: 0, w: 5, h: 5 },
{ i: "b", x: 1, y: 0, w: 3, h: 2 },
{ i: "c", x: 4, y: 0, w: 1, h: 2 }
];
return (
<GridLayout
className="layout"
layout={layout}
cols={12}
rowHeight={30}
width={1200}
onResizeStop={function(event) {
this.myRef.current.chart.setSize(this.conRef.current.clientWidth,this.conRef.current.clientHeight)
console.log('hello', event);
}.bind(this)}
>
<div ref={this.conRef} style={{ backgroundColor: "#00000000" }} key="a">
<HighchartsReact
ref= {this.myRef}
containerProps={{ style: { width: '100%', height: '100%' } }}
options={options}
highcharts={Highcharts}
/>
</div>
<div style={{ backgroundColor: "red" }} key="b">
b
</div>
<div style={{ backgroundColor: "blue" }} key="c">
c
</div>
</GridLayout>
);
}
}
export default MyFirstGrid;

Victory Charts: Using labels with bar charts

I am leveraging VictoryCharts to add charts to my React app. I am trying to accomplish something like:
I combed through the docs and was not able to find a way to add Labels to a single bar chart.
Things I have tried
Nesting <VictoryLabel> andunder``` --> The axes show up and the docs recommend using VictoryGroup
Nesting <VictoryLabel> andunder``` --> VictoryGroup does not support VictoryLabel
Tried making a standalone <VictoryBar> & <VictoryLabel> and embedding it into <svg> --> Cannot see the chart contents on the page
This is the snippet I have right now:
import Box from '#material-ui/core/Box';
import React from 'react';
import { VictoryAxis, VictoryBar, VictoryChart, VictoryContainer, VictoryLabel, VictoryTheme } from 'victory';
const SampleChart = ({ stat=25, title = 'Sample' }) => (
<Box ml={5}>
<svg height={60} width={200}>
<VictoryLabel text={title.toLocaleUpperCase()} textAnchor='start' verticalAnchor='end' />
<VictoryBar
barWidth={10}
data={[{ y: [stat], x: [1] }]}
domain={{ y: [0, 100], x: [0, 1] }}
horizontal
labels={d => d.y}
labelComponent={
<VictoryLabel verticalAnchor='end' textAnchor='start' />
}
standalone
style={{ parent: { height: 'inherit' } }}
theme={VictoryTheme.material}
/>
</svg>
</Box>
);
ReactDOM.render(<SampleChart />, document.querySelector("#app"))
<div id='app'></div>
You could use an axis to this effect like so:
const CHART_WIDTH = 800;
const val = 28
function BarChart() {
return (
<div style={{ width: CHART_WIDTH }}>
<VictoryChart height={200} width={CHART_WIDTH}>
<VictoryAxis
dependentAxis
tickValues={[0,100]}
offsetY={190}
tickFormat={t => t===0 ? 'average age' : val}
style={{axis: { stroke: 'none'}}}
/>
<VictoryBar
barWidth={10}
data={[{ y: [45], x: [1] }]}
domain={{ y: [0, 100], x: [0, 1] }}
horizontal
/>
</VictoryChart>
</div>
);
}
https://codepen.io/anon/pen/RmaxOd?editors=0110#0
Not exactly what you wanted, but it gets the job done, and you can format the tick labels or provide custom components to make it look like your desired result.

Resources