How to change cart icon state using React Hooks - reactjs

I have two components, one will contain a button that will trigger the cart icon change when clicked, while the second component will contain the cart icon to be changed. I have tried but i have not been able to achieve this.Here is an image to explain better
Component A
import React,{useState} from 'react'
const Cart = () => {
const [itemCount, setItemCount] = useState('');
return (
<div>
<button
style={{width: '10%', height: '10%', padding:'20px'}}
onClick={() => {
setItemCount(itemCount + 1);
}}
>
{" "}
</button>
</div>
)
}
export default Cart
Component B
import React from 'react'
import Cart from './Cart'
const CartShow = (props) => {
return (
<div style={{border: '2px solid red', background: 'black', width: '30%', margin: '100px',
padding: '30px'}}>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path d="M9 22C9.55228 22 10 21.5523 10 21C10 20.4477 9.55228 20 9 20C8.44772 20 8 20.4477
8 21C8 21.5523 8.44772 22 9 22Z" stroke="white" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round"/>
<path d="M20 22C20.5523 22 21 21.5523 21 21C21 20.4477 20.5523 20 20 20C19.4477 20 19
20.4477 19 21C19 21.5523 19.4477 22 20 22Z" stroke="white" stroke-width="2" stroke-
linecap="round" stroke-linejoin="round"/>
<path d="M1 1H5L7.68 14.39C7.77144 14.8504 8.02191 15.264 8.38755 15.5583C8.75318 15.8526
9.2107 16.009 9.68 16H19.4C19.8693 16.009 20.3268 15.8526 20.6925 15.5583C21.0581 15.264
21.3086 14.8504 21.4 14.39L23 6H6" stroke="white" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round"/>
{props.itemCount}</svg>
<Cart/>
</div>
)
}
export default CartShow

Assuming your code works except the state change. following should work(not tested):
Component A
const Cart = (props) =>
<div>
<button
style={{width: '10%', height: '10%', padding:'20px'}}
onClick={() => props.setItemCount(props.itemCount + 1)}
>
{" "}
</button>
</div>
export default Cart
Component B
import React,{useState} from 'react'
import Cart from './Cart'
const CartShow = () => {
const [itemCount, setItemCount] = useState(0);
return (
<div style={{border: '2px solid red', background: 'black', width: '30%', margin: '100px',
padding: '30px'}}>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path d="M9 22C9.55228 22 10 21.5523 10 21C10 20.4477 9.55228 20 9 20C8.44772 20 8 20.4477
8 21C8 21.5523 8.44772 22 9 22Z" stroke="white" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round"/>
<path d="M20 22C20.5523 22 21 21.5523 21 21C21 20.4477 20.5523 20 20 20C19.4477 20 19
20.4477 19 21C19 21.5523 19.4477 22 20 22Z" stroke="white" stroke-width="2" stroke-
linecap="round" stroke-linejoin="round"/>
<path d="M1 1H5L7.68 14.39C7.77144 14.8504 8.02191 15.264 8.38755 15.5583C8.75318 15.8526
9.2107 16.009 9.68 16H19.4C19.8693 16.009 20.3268 15.8526 20.6925 15.5583C21.0581 15.264
21.3086 14.8504 21.4 14.39L23 6H6" stroke="white" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round"/>
{itemCount}</svg>
<Cart itemCount={itemCount} setItemCount={setItemCount} />
</div>
)
}
export default CartShow
Edit: to show the numbers on on the cart, check this link: How to put the number at top right corner of cart icon?

Since Cart is a child of CartShow you should move the state to CartShow ( or have a different parent component that contains both of them ). Then pass a func down to Cart to update itemCount

Related

How to use conditional rendering using class name in React? [duplicate]

This question already has answers here:
React Js conditionally applying class attributes
(24 answers)
Closed 1 year ago.
import { display } from '#mui/system';
import React from 'react';
import "../user_config/user_page.css"
export default function FileUploadButton({showBtn, setShowBtn,value,...rest}) {
const handelClick = () => {
setShowBtn(false);
};
return (
<div style={{ position: 'relative', display: 'inline-block' ,marginTop:'10px'}} className="big-size-file">
<button style={{ padding: '1px 12px', border: ' 1px solid #989797', borderRadius: '4px', color: '#727171',cursor:"pointer !important" }}>
{value && showBtn ? 'Replace file' : 'Choose file'}
</button>
{value && showBtn?<span title={value} style={{fontSize: '9px', color: 'blue', marginLeft:'10px' }}>{value}<button type="button" onClick={handelClick} className="float-right rounded-md text-blue-500 hover:text-gray-500 focus:outline-none " className={"big-size-file"?'marginTop:-17px':'margTop:11px'}>
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-3 w-3 z-100"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
clipRule="evenodd"
/>
</svg>
</button></span>:<span>No file chosen</span>}
<input type='file' {...rest} className="fileStyle" style={{ position: 'absolute', zIndex: 2, opacity: 0, height: '100%', top: 0, bottom: 0, left: 0, right: 0 }} />
</div>
)
}
also big-size-file CSS property
.big-size-file {
max-width: 190px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
display: block;
}
How can I use that classname in conditional rendering that if classname is "big-size-file" then button marginTop is -17px or else marginTop 11px?
you can use state for storing your inital default value.
make two css classes with different styling
const [sty,setSty]=useState("default css class name here")
if you have some event then change it state set classname of your css.Now for your else part just change the state or make another state for storing name of diffeent css class
{value && showBtn?<span title={value} className={sty}>{value}<button type="button" onClick={handelClick} className="float-right rounded-md text-blue-500 hover:text-gray-500 focus:outline-none " className={"big-size-file"?'marginTop:-17px':'margTop:11px'}>
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-3 w-3 z-100"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
clipRule="evenodd"
/>
</svg>
</button></span>:<span>No file chosen</span>}

How to style an SVG using React styled components by passing the SVG as prop?

I have this SVG, imported from figma:
import React from 'react';
function CloseIcon() {
return (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g clip-path="url(#clip0_5301_20199)">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M19.8539 4.85394C20.0491 4.65868 20.0491 4.3421 19.8539 4.14683C19.6586 3.95157 19.342 3.95157 19.1468 4.14683L12.0007 11.2929L4.85372 4.14634C4.65845 3.95108 4.34187 3.95109 4.14661 4.14636C3.95136 4.34162 3.95136 4.65821 4.14663 4.85346L11.2936 12L4.14688 19.1467C3.95162 19.342 3.95162 19.6586 4.14688 19.8538C4.34214 20.0491 4.65873 20.0491 4.85399 19.8538L12.0007 12.7071L19.1467 19.8529C19.342 20.0481 19.6586 20.0481 19.8539 19.8528C20.0491 19.6576 20.0491 19.341 19.8538 19.1457L12.7078 12L19.8539 4.85394Z"
fill="#00A989"
/>
</g>
<defs>
<clipPath id="clip0_5301_20199">
<rect width="24" height="24" fill="white" />
</clipPath>
</defs>
</svg>
);
}
export default CloseIcon;
The SVG is then imported in my component, rendered correctly on the screen as the original style coming from Figma. But when I do style it with styled components, any style is not applied. What is the problem?
import CloseIcon from '../../../Icons/CloseIcon';
import styled from 'styled-components';
<ClosingIcon
aria-label="Close Modal"
onClick={() => setShowModal((prev) => !prev)}
/>
const ClosingIcon = styled(CloseIcon)`
cursor: pointer;
position: absolute;
top: 14px;
right: 32px;
/* width: 32px;
height: 32px; */
padding: 0;
z-index: 10;
`;
you need to pass classname prop to the child component,
function CloseIcon({ className }) {
return (
<svg
className={className} --> like this
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g clipPath="url(#clip0_5301_20199)">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M19.8539 4.85394C20.0491 4.65868 20.0491 4.3421 19.8539 4.14683C19.6586 3.95157 19.342 3.95157 19.1468 4.14683L12.0007 11.2929L4.85372 4.14634C4.65845 3.95108 4.34187 3.95109 4.14661 4.14636C3.95136 4.34162 3.95136 4.65821 4.14663 4.85346L11.2936 12L4.14688 19.1467C3.95162 19.342 3.95162 19.6586 4.14688 19.8538C4.34214 20.0491 4.65873 20.0491 4.85399 19.8538L12.0007 12.7071L19.1467 19.8529C19.342 20.0481 19.6586 20.0481 19.8539 19.8528C20.0491 19.6576 20.0491 19.341 19.8538 19.1457L12.7078 12L19.8539 4.85394Z"
fill="#00A989"
/>
</g>
<defs>
<clipPath id="clip0_5301_20199">
<rect width="24" height="24" fill="white" />
</clipPath>
</defs>
</svg>
);
}
reference : https://styled-components.com/docs/advanced#existing-css

React Native - SVG Image is not scaling across different device dimensions

I am trying to develop a simple screen in react native where it displays an svg image. I am trying to make the svg image use the full device width and height (100%). But the problem is, it is not consistent across different devices. For example, it is rendering properly in Iphone 8 Plus but not scaling properly in Ipad or Iphone 8. I heard the SVG files are scalable across all devices without losing quality. But I am not sure what I am missing here. I have posted the code and images below for reference.
Before posting here, I have did a considerable amount of research in Github and here as well.
I have also followed the steps mentioned in one of the similar posts (How to find correct values for width, height and viewBox with react-native-svg) but its not working. Can any please guide me on the right direction to fix the issue.
React Native Screen Component Code
import * as React from "react";
import Svg, { Defs, G, Path, Text, TSpan, Circle } from "react-native-svg";
/* SVGR has dropped some elements not supported by react-native-svg: style */
import { Dimensions, View } from "react-native";
function SvgComponent(props) {
const originalWidth = 1080;
const originalHeight = 1920;
const aspectRatio = originalWidth / originalHeight;
const windowWidth = Dimensions.get("window").width;
return (
<View style={{ width: windowWidth, aspectRatio }}>
<Svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 1080 1920"
width="100%"
height="100%"
>
<Defs></Defs>
<G id="prefix__Layer_2" data-name="Layer 2">
<G id="prefix__Layer_1-2" data-name="Layer 1">
<Path fill="#006837" d="M.5.5h1079v1919H.5z" />
<Path d="M1079 1v1918H1V1h1078m1-1H0v1920h1080V0z" />
<Text
transform="matrix(1.5 0 0 1 13 148.09)"
fontFamily="ArialMT,Arial"
fill="#fff"
fontSize={106}
>
<TSpan className="prefix__cls-3">{"T"}</TSpan>
<TSpan x={62.83} y={0}>
{"O"}
</TSpan>
<TSpan x={145.28} y={0} letterSpacing="-.02em">
{"P"}
</TSpan>
<TSpan x={214.07} y={0} />
<TSpan x={243.52} y={0} letterSpacing="-.07em">
{"P"}
</TSpan>
<TSpan x={306.35} y={0} letterSpacing={0}>
{"AGE"}
</TSpan>
<TSpan className="prefix__cls-3" x={530.21} y={0} />
<TSpan x={557.74} y={0}>
{"TS"}
</TSpan>
</Text>
<Text
transform="matrix(1.5 0 0 1 13 1888.09)"
fontSize={79}
fontFamily="ArialMT,Arial"
fill="#fff"
>
{"BOT"}
<TSpan className="prefix__cls-8" x={162.4} y={0}>
{"T"}
</TSpan>
<TSpan x={209.23} y={0}>
{"OM "}
</TSpan>
<TSpan x={358.43} y={0} letterSpacing="-.07em">
{"P"}
</TSpan>
<TSpan x={405.26} y={0}>
{"AGE"}
</TSpan>
<TSpan className="prefix__cls-8" x={572.09} y={0} />
<TSpan x={592.62} y={0}>
{"TS"}
</TSpan>
</Text>
<Circle className="prefix__cls-10" cx={514.5} cy={396.5} r={129} />
<Path d="M514.5 268a128.51 128.51 0 11-90.86 37.64A127.66 127.66 0 01514.5 268m0-1A129.5 129.5 0 10644 396.5 129.5 129.5 0 00514.5 267z" />
<Circle className="prefix__cls-10" cx={179.5} cy={729.5} r={129} />
<Path d="M179.5 601a128.51 128.51 0 11-90.86 37.64A127.66 127.66 0 01179.5 601m0-1A129.5 129.5 0 10309 729.5 129.5 129.5 0 00179.5 600z" />
<Circle className="prefix__cls-10" cx={852.5} cy={748.5} r={129} />
<Path d="M852.5 620a128.51 128.51 0 11-90.86 37.64A127.66 127.66 0 01852.5 620m0-1A129.5 129.5 0 10982 748.5 129.5 129.5 0 00852.5 619z" />
<Circle className="prefix__cls-10" cx={514.5} cy={1007.5} r={129} />
<Path d="M514.5 879a128.51 128.51 0 11-90.86 37.64A127.66 127.66 0 01514.5 879m0-1A129.5 129.5 0 10644 1007.5 129.5 129.5 0 00514.5 878z" />
<Path
className="prefix__cls-10"
d="M36.99 1244.17l-28.95-91.2 64.51-70.67 93.46 20.53 28.95 91.2-64.51 70.67-93.46-20.53z"
/>
<Path d="M72.72 1082.85l92.9 20.4 28.77 90.65-64.11 70.25-92.9-20.4-28.77-90.65 64.11-70.25m-.34-1.1l-64.9 71.1 29.12 91.75 94 20.65 64.9-71.1-29.1-91.75-94-20.65z" />
<Path
className="prefix__cls-10"
d="M863.74 1280.56l-66.18-120.49 71.26-117.56 137.44 2.93 66.18 120.49-71.26 117.56-137.44-2.93z"
/>
<Path d="M869.1 1043l136.86 2.92 65.9 120-71 117.07-136.86-2.92-65.9-120 71-117.07m-.56-1l-71.56 118 66.46 121 138 3 71.56-118-66.46-121-138-3z" />
<Path
className="prefix__cls-10"
d="M293.27 1553.17l35.61-150.02 147.73-44.18 112.12 105.86-35.61 150.02-147.73 44.18-112.12-105.86z"
/>
<Path d="M476.48 1359.53L588.18 1465l-35.48 149.46-147.18 44L293.82 1553l35.48-149.47 147.18-44m.26-1.12l-148.28 44.34-35.75 150.59 112.55 106.25 148.28-44.34 35.75-150.59-112.55-106.25z" />
<Path
className="prefix__cls-10"
d="M708.09 1692.49a21.08 21.08 0 01-20.4-26l54.77-230.76a21 21 0 0120.54-16.16 20.61 20.61 0 0114 5.37l185.77 166a21.07 21.07 0 01-8.55 36l-240.55 64.78a21.15 21.15 0 01-5.58.77z"
/>
<Path d="M763 1419.07v1a20.16 20.16 0 0113.61 5.24l185.77 166a20.55 20.55 0 01-8.35 35.18l-240.55 64.79a21 21 0 01-5.43.73 20.58 20.58 0 01-19.92-25.33L743 1435.9a20.54 20.54 0 0120-15.83v-1m0 0a21.53 21.53 0 00-21 16.59l-54.8 230.76a21.49 21.49 0 0026.58 25.8l240.55-64.78a21.56 21.56 0 008.76-36.9l-185.77-166a21.27 21.27 0 00-14.29-5.5z" />
</G>
</G>
</Svg>
</View>
);
}
export default SvgComponent;
Perfect Rendering in Iphone 8 Plus
Bad Rendering in IPad

How to make a line break in svg

I have the following SVG of dynamically rendered pie chart using react-minimal-pie-chart :-
<svg viewBox="0 0 100 100" width="100%" height="100%"><path d="M 75 50 A 25 25 0 0 1 54.34120444167326 74.6201938253052" fill="none" stroke-width="50" stroke="#8dcd81"><title>Excellent</title></path><path d="M 54.34120444167326 74.6201938253052 A 25 25 0 0 1 26.507684480352285 41.449496416858295" fill="none" stroke-width="50" stroke="#eefa6b"><title>Good</title></path><path d="M 26.507684480352285 41.449496416858295 A 25 25 0 0 1 75 49.99999999999999" fill="none" stroke-width="50" stroke="#FF6382"><title>Weak</title></path><text dominant-baseline="central" x="50" y="50" dx="19.151111077974452" dy="16.06969024216348" text-anchor="middle" style="font-size: 5px;">22 %Excellent</text><text dominant-baseline="central" x="50" y="50" dx="-19.15111107797445" dy="16.069690242163485" text-anchor="middle" style="font-size: 5px;">33 %Good</text><text dominant-baseline="central" x="50" y="50" dx="4.341204441673249" dy="-24.620193825305204" text-anchor="middle" style="font-size: 5px;">44 %Weak</text></svg>
This is my Reactjs code:-
const Element = (props) => {
return (
<text
dominant-baseline="central"
x={props.x}
y={props.y}
dx={props.dx}
dy={props.dy}
text-anchor="middle"
style={{ fontSize: "5px" }}
>
{`${Math.round(props.dataEntry.percentage)} %`}
{props.dataEntry.title}
</text>
);
};
This is codesandbox full Reactjs example:-
https://codesandbox.io/s/throbbing-moon-ejs67?file=/src/App.js
How can i line break between the texts (excellent - good ..) and their percentage .
As Danny says - just stick in a tspan. These settings seem to work ok:
const Element = (props) => {
return (
<text
dominant-baseline="central"
x={props.x}
y={props.y}
dx={props.dx}
dy={props.dy}
text-anchor="middle"
style={{ fontSize: "5px" }}
>
{`${Math.round(props.dataEntry.percentage)} %`}
<tspan dx="-12" dy="5">
{props.dataEntry.title}
</tspan>
</text>
);
};

How to generate an svg image from multiple small svg components?

I have the below svg component. I want to stack multiple same svg components horizontally and vertically, to generate a bigger svg image in a grid.
I can stack them together but how do I convert it to an svg?
Please suggest, and if there is any package I can use. Thanks.
SVG Component
import React from "react";
import "./styles.css";
export default function MySVG() {
return (
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink" width="40" height="40" viewBox="0 0 40 40">
<defs/>
<g/>
<g transform="scale(1,1)">
<g transform="scale(1,1)">
<rect id="cell" fill="rgb(16,28,138)" stroke="none" x="0" y="0" width="40" height="40" fill-opacity="0.40784313725490196"/>
</g>
<path fill="none" stroke="rgb(163,127,18)" paint-order="fill stroke markers" d=" M 0 0 L 0 40" stroke-opacity="0.7294117647058823" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>
<path fill="none" stroke="rgb(163,127,18)" paint-order="fill stroke markers" d=" M 40 0 L 40 40" stroke-opacity="0.7294117647058823" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>
<path fill="none" stroke="rgb(163,127,18)" paint-order="fill stroke markers" d=" M 0 0 L 40 0" stroke-opacity="0.7294117647058823" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>
<path fill="none" stroke="rgb(163,127,18)" paint-order="fill stroke markers" d=" M 0 40 L 40 40" stroke-opacity="0.7294117647058823" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2"/>
</g>
</svg>
);
}
App Component
import React from "react";
import MySVG from "./MySVG";
import "./styles.css";
export default function App() {
return [...Array(5).keys()].map((i) => <MySVG key={i} />);
}
CodeSandBox Link

Resources