Stacked Bar graph with ReactJS - javascript

I have to do a single stacked bar graph getting the data from an API, but I am finding some issues.
1- On one hand, the data I get is not rounded, even if I use %.
2- On the other hand, the total I get is not always 100%, then the bar is sometimes a few pixels shorter and sometimes a few pixels longer than expected.
import styled from 'styled-components'
import { Data } from '../../Types'
const Colors: Record<string, string> = {
warning: 'yellow',
good: 'green',
danger: 'red',
}
const StackedBar = (props: {
title?: string
Data: Data | null
}) => {
return (
<div>
<div
style={{
display: 'flex',
flex: '1 1 auto',
alignSelf: 'auto',
}}
>
{props && props.Data ? (
props.Data.items.map((item) => {
const percentage =
(item.count / items_total) * 100
return (
<Rectangle
percentage={percentage}
color={
itemColors[item.items_total]
}
/>
)
})
) : (
<Rectangle percentage={100} color="grey" />
)}
</div>
</div>
)
}
export default StackedBar
const Rectangle = styled.div<{ percentage: number; color: string }>`
height: 20px;
width: ${(props) => props.percentage}%;
background-color: ${(props) => props.color};
`
const NormalBold = styled.p`
font-weight: 700;
font-size: var(--font-size-normal);
`

percentage =(item.count / items_total) * 100, here items_ total is not defined, check the code again. I think it should be item.items_total.
for rounding use Math.round(percentage) to round off values.
I think this should resolve your issues.

Related

Using spread operator in Styled-Components

I'm new to React and React-Spring and practicing how to use it.
There's really basic code from React-Spring document, and I want to convert it using styled-components.
I converted code to styled-components but don't know how to change ...springs in styled-components.
Can I know how to apply it with using styled-components??
document code: codesandbox
import '/index.css'
import { useSpring, animated } from '#react-spring/web'
export default function MyComponent() {
const springs = useSpring({
from: { x: 0 },
to: { x: 100 },
})
return (
<animated.div
style={{
width: 80,
height: 80,
background: '#ff6d6d',
borderRadius: 8,
// don't know how to conver this part
...springs,
}}
/>
)
}
my code: codesandbox
import { useSpring, animated } from "#react-spring/web";
import styled from "styled-components";
export default function App() {
const springs = useSpring({
from: { x: 0 },
to: { x: 100 }
});
return (
<Spring>
<animated.div className="box">hi</animated.div>
</Spring>
);
}
const Spring = styled.div`
border: 3px solid black;
.box {
width: 80px;
height: 80px;
background: #ff6d6d;
border-radius: 8px;
//this part doesn't work
...springs;
}
`;
Having styled components or not doesn't affect your code: you should still spread the springs object directly into <animated.div>.
return (
<Spring>
<animated.div className="box" style={{ ...springs }} />
</Spring>
);
If you truly want to offload all the styling to styled-components, you can create a new styled component that uses animated.div internally, i.e.:
const SpringBox = styled(animated.div)`
width: 80px;
height: 80px;
background: #ff6d6d;
border-radius: 8px;
`;
Then you can update your template as such: but note that you are still spreading the springs in the JSX template and not passing it via styled components:
return (
<Spring>
<SpringBox style={{ ...springs }} />
</Spring>
);

Why is my react-tooltip sometimes displaying on the parent element?

I've made a covid related travel map here: Where Can We Go Now
It's a static react JS website, billy basic with create-react-app. It uses amongst other things the excellent React Simple Maps (kudos to the creator) and react-tooltip.
Expected behaviour:
Locally the tooltip works fine when tested with npm run start
I move my mouse over a country and the tooltip displays some relevant information approximately where my mouse is on the map.
The Problem:
. . . once published with npm run build sort of works but strange things happen.
Please follow link to website to observe, but in short, if the sea (i.e. an area that isn't a country - so not defined by an svg in the topojson) is clicked then the tooltip is place at the top centre of the whole map itself.
Some bits of relevant code:
Index.js (snippet):
const [content, setContent] = useState("");
return (
<div><h1> Where can we go on holiday ?* </h1>
<MapChart setTooltipContent={setContent}/>
<ReactTooltip html={true}>{content}</ReactTooltip>
</div>
);
}
MapChart.js (snippet):
return (
<div>
<p><small>*Right now in the UK: {data.headlineAdviceNow} Last updated at {updateString}</small></p>
<ComposableMap
projectionConfig={{
rotate: [-40, -30, 10],
scale: 1600
}}
width={mapWidth}
height={mapHeight}
style={{ maxWidth: "100%", height: "80vh", background: "#b3b3b3", borderStyle: "solid", borderColor: "white", margin: 0.5,
borderRadius: 20 }}
>
<ZoomableGroup zoom={zoom} center={center} translateExtent={[
[0, 0],
[mapWidth, mapHeight]
]} maxZoom={15} data-tip="">
<Sphere stroke="#E4E5E6" strokeWidth={0.5} />
<Graticule stroke="#E4E5E6" strokeWidth={0.2} />
{!loading && (<Geographies geography={geoUrl}>
{({ geographies }) =>
geographies.map((geo) => {
const d = data.countries.find((s) => s.country.iso_a3 === geo.properties.ISO_A3);
return (
<Geography
key={geo.rsmKey}
geography={geo}
style={{
default: {
outline: "none",
stroke: "grey",
strokeWidth: "1",
strokeLinecap: "butt",
fill: d ? colorScale(d[attr]) : "#F5F4F6"
},
hover: {
outline: "none",
stroke: "black",
strokeWidth: "3",
strokeLinecap: "butt",
fill: d ? colorScale(d[attr]) : "#F5F4F6"
},
pressed: {
outline: "none"
}
}}
onMouseEnter={() => {
const NAME = geo.properties.NAME;
const travelIndex = d ? d["indexDescription"] : "Unknown";
//const border = d ? d["borderStatusString"] : "Unknown";
const returnStatus = d ? (fromCountry==="GBR" ? d["ukCategory"] : "TBC") : "Unknown";
const vaccinePc = d ? d.vaccineData["total_vaccinations_per_hundred"] + "%" : "NK";
const arrival = (() => {try{ return d["restrictionsFrom"][data["iomKeys"].indexOf(fromCountry)].split("-") } catch {return [4,""]}});
const arrivalLevel = rstrctLkup[arrival()[0]]["short"]
//const arvlRtns = arrival()[1].length===0 ? arrival()[1] : arrival()[1].split(",")
//var text =""
//var i;
//for (i = 0; i < arvlRtns.length; i++) {
// if (data["restrictionDefs"][arvlRtns[i]]) {
// if (i===0) {text="<br />Arrival Details:<br />"}
// text += data["restrictionDefs"][arvlRtns[i]] + "<br>";
//}}
setTooltipContent(`<b>${NAME.toUpperCase()}:</b> ${travelIndex}<br /><p style="text-align: left"><b>RISK FACTORS</b><br />Vaccinated: ${vaccinePc}<br /><br /><b>CURRENT RESTRICTIONS</b><br />Entry: ${arrivalLevel}<br />Return: ${returnStatus}</p>`);
}}
onMouseLeave={() => {
setTooltipContent("");
}}
/>
);
})
}
</Geographies>
)}
</ZoomableGroup>
</ComposableMap>
</div>
);
};
export default memo(MapChart);
What I've tried:
Variations of setting tooltip position, and moving where and what data-tip="" is. Also, banging head on wall.
I was inaccurate in my question, so didn't provide relevant details that was the source of the problem.
I publish with github actions and this was the fix:
yarn install --frozen-lockfile
The frozen lockfile was the key to make sure I was using the exact versions of relevant packages as I had been testing locally. I'd erroneously suggested I was using npm.

How to draw an arrow from a parent div to all children divs?

I have a reusable React list component that can have nested children and I want to draw an arrow from the parent div to all direct children divs like the picture below.
List Component Image
Here is an example of a nested list component:
import React from 'react';
import ListElement from './ListElement.js';
const List = () => (
<>
<ListElement>
<ListElement>
<ListElement>
<ListElement />
<ListElement>
<ListElement />
</ListElement>
</ListElement>
<ListElement />
</ListElement>
<ListElement />
</ListElement>
<ListElement />
</>
);
export default List;
The ListElement component looks something like this:
import React from 'react';
const ListElement = props => {
const indentationStyle = { paddingLeft: `${3 * props.indent}rem`,
position: 'relative'};
const lineStyle = {
left: `${2 + 3 * (props.indent - 1.2)}rem`,
};
const tile = (
<div style={indentationStyle}>
{props.indent > 0 ? (
<div className={'arrow-line-container'} style={lineStyle}>
<div className={'arrow-line'}/>
<div className={'curve-arrow-line'}/>
</div>
) : null}
<div
style={{
border: '1px solid black',
padding: '1rem',
marginBottom: '1rem',
}}
>
I am a ListElement
</div>
</div>
);
const getChildren = () => {
let elements = React.Children.toArray(props.children);
// increase indent prop of each child and assign what number child it is in the list
elements = elements.map((element, index) => {
return React.cloneElement(element, {
...element.props,
indent: props.indent + 1,
childNumber: index,
});
});
return elements;
};
const childTiles = <div className={'child-tile'}>{getChildren()}</div>;
const arrowStyle = {
backgroundPosition: `${1.3 + 3 * (props.indent - 1)}rem`,
};
return (
<>
<ul className={'no-bullet'}>
<li
className={props.indent === 0 ? 'no-arrow' : 'arrow'}
style={arrowStyle}
>
{tile}
</li>
{props.children ? childTiles : null}
</ul>
</>
);
};
ListElement.defaultProps = {
childNumber: 0,
indent: 0,
};
export default ListElement;
and the css looks like this:
ul.no-bullet {
list-style-type: none;
padding: 0;
margin: 0;
}
.arrow-line {
border-left: 2px solid #6a6969;
content: "";
position: absolute;
height: 65%;
}
li.arrow {
background: url("./arrow.png") no-repeat;
}
li.no-arrow {
display: block;
}
Currently, I am creating the list with <li> elements and changing the bullet to an image of the arrow. I want to draw the lines from the parent and attach them to the arrows at each child. I am struggling with calculating the correct height of the line and the position for the top of the line. Any suggestions are appreciated.
Here is a link to the Plunker: https://plnkr.co/edit/GFrriWfJyeur7MRh?open=Hello.js&deferRun=1&preview
I managed to find a solution by only drawing one line at the last child and using offsetTop and getBoundingClientRect().height to calculate the position and height of the arrow-line. Working solution here: https://plnkr.co/edit/SFzgiZi1dckRa79C

how can i display round dot for active status in react

In older code of react it just display the text active or in active for an user. Now I want to replace it to red or green small dot how can I do it.
CSS
div .colored-circle {
display: inline-block;
margin-left: 5px;
margin-right: 5px;
margin-bottom: -2px;
border-radius: 50%;
border-style: solid;
border-width: 0.5px;
border-color: black;
height: 20px;
width: 20px;
}
Component:
const ColoredCircle = ({ color }) => {
const styles = { backgroundColor: color };
return color ? (
<Fragment>
<span className="colored-circle" style={styles} />
</Fragment>
) : null;
};
export default ColoredCircle;
Use the same logic you used to show 'active' or 'inactive' and instead of text add a div with css or img of the desired color.
If you happen to use material UI, you can do like this:
import React, { Fragment } from "react";
import { makeStyles } from "#material-ui/core";
const RADIUS_DOT = 1.5;
const useStyles = makeStyles((theme) => ({
circle: {
borderRadius: RADIUS_DOT,
height: RADIUS_DOT * 2,
width: RADIUS_DOT * 2,
padding: 0,
},
}));
const ColoredCircle = ({ color }) => {
const styles = { backgroundColor: color };
const classes = useStyles();
return color ? (
<Fragment>
<span className={classes.circle} style={styles} />
</Fragment>
) : null;
};
export default ColoredCircle;
you can use this package, can be helpful
npm i react-color-circle
import Circle from '#uiw/react-color-circle';
return (
<Circle
colors={[ '#F44E3B' ]}
/>);

React inline style - style prop expects a mapping from style properties to values, not a string

I am trying to set inline styles in my React application. In this case, for a span:
<span className="myClass" style={{float : 'left', paddingRight : '5px'}} > </span>
React tells me:
Uncaught Invariant Violation: The style prop expects a mapping from
style properties to values, not a string. For example,
style={{marginRight: spacing + 'em'}} when using JSX. This DOM node
was rendered by `SentenceView
I am not quite sure what it means.
PS: I have tried different versions, so I did paddingRight: 5 as well as paddingRight: 5 + 'px' as well as paddingRight : 5px, but I didn't have any success!
Use "styles" prop instead of style
<span className="myClass" style={{float : 'left', paddingRight : '5px'}} > </span>
Here is a great reference from W3Schools which also shows you how to create an object with styling information, and refer to it in the style attribute:
reference for how to style React using CSS
There some ways to set style for React Components.
https://facebook.github.io/react/docs/context.html
https://github.com/facebookincubator/create-react-app
using style={css_object} or style={{color: this.props.color}}
using className="your-class-name"
React REPL
https://jscomplete.com/repl
1 style Object
// <span style={styles}>
const styles = {
color: "red",
background: "#0f0",
fontSize: "32px"
};
const BTN = (props) => {
return (
<div>
My name is <button>{props.name}</button>
<hr/>
I'm <span style={styles}>{props.age}</span> yeas old!
</div>
);
};
const infos = {
name: "xgqfrms",
age: 23
};
ReactDOM.render(<BTN {...infos} />, mountNode);
// <span style={{color: styles.color}}>
const styles = {
color: "red",
background: "#0f0",
fontSize: "32px"
};
const BTN = (props) => {
return (
<div>
My name is <button>{props.name}</button>
<hr/>
I'm <span style={{color: styles.color}}>{props.age}</span> yeas old!
</div>
);
};
const infos = {
name: "xgqfrms",
age: 23
};
ReactDOM.render(<BTN {...infos} />, mountNode);
2 className & stylesheet.css
import './styles.css';
/*
.classname-color{
color: "red";
background: "#0f0";
}
*/
const BTN = (props) => {
return (
<div>
My name is <button>{props.name}</button>
<hr/>
I'm <span className="classname-color">{props.age}</span> yeas old!
</div>
);
};
const infos = {
name: "xgqfrms",
age: 23
};
ReactDOM.render(<BTN {...infos} />, mountNode);
.classname-color{
color: "red";
background: "#0f0";
}
JSX and HTML are different. See the graphic below from Udemy:
In HTML it is
<div style="background-color: red;"></div>
In JSX you write
<div style={{ backgroundColor: 'red' }}></div>
Conditional inline formatting are different in both.
This is the way how you can define and use inline style with react.
/**
* Style definitions.
*/
const STYLE = {
infoColor: {
color: 'green'
},
warningColor: {
color: 'orange'
},
errorColor: {
color: 'red'
}
};
/**
* Component
*/
class Welcome extends React.Component {
/**
* Rendering into the DOM.
*/
render() {
return (
<div>
<h2 style={STYLE.infoColor}>Welcome!</h2>
)
}
}
when we use inline styling in react we should always use style={{styleproperties}}
Error:
<input style="margin:0 15px 0 0"/>
Solution:
<input style={{margin:"0 15px 0 0"}}/>
don't wrap the {{}} in double quotes or string

Categories