import style from './style.module.scss';
import countries from './data';
import Tippy from '#tippyjs/react';
import 'tippy.js/dist/tippy.css';
const AfricaPage = () => {
return (
<div className={style.africa}>
<svg width="504" height="565" viewBox="0 0 504 565" xmlns="http://www.w3.org/2000/svg">
{countries.map((country, idx) => {
return <>
<Tippy content={country.name}>
<path d={country.d} fill={country.fill} stroke={country.stroke} />
</Tippy>
</>
})}
</svg>
</div>
);
}
export default AfricaPage;
Tried adding <Tippy content={country.name}{country.description>to content of Tippy, but did not work. How can i get description to show in same tooltip box? How would I include description?
Related
Is it possible to import dynamically react-icons if each of icon is a separate component?
My code looks like this:
import React from 'react';
import { Icon1, Icon2, Icon3, Icon4 } from 'react-icons/ri';
const Foo = () => (
<div className="xxx">
<div className="y">
<Icon1 />
</div>
<div className="y">
<Icon2 />
</div>
<div className="y">
<Icon3 />
</div>
<div className="y">
<Icon4 />
</div>
</div>
);
export default Foo;
and would want it to look close to this:
import React from 'react';
const Buttons = () => {
const iconsList = ['Icon1', 'Icon2', 'Icon3'];
const renderIcon = (icon) => {
const Icon = icon;
return (
<div className="y">
<Icon />
</div>
)
}
return (
<div className="d-flex align-items-center justify-content-end">
{iconsList.map(icon => renderIcon(icon))}
</div>
)
};
export default Buttons;
The problem I face is how to make the import of icons work there if I didn't want to import all icons using *.
Also the problem is that if I make
import { Icon1, Icon2, Icon3, Icon4 } from 'react-icons/ri'
at the top, it still doesn't work for the second version of code.
You have to replace the strings values of your icons in the iconsList array with the Icon component itself.
Just change :
const iconsList = ['Icon1', 'Icon2', 'Icon3'];
to :
const iconsList = [Icon1, Icon2, Icon3];
And add a key to prevent Each child in a list should have a unique "key" prop.Warning like this :
{iconsList.map((icon, index) => renderIcon(icon, index))}
and :
const renderIcon = (icon, index) => {
const Icon = icon;
return (
<div className="y" key={index}>
<Icon />
</div>
);
};
this is an example in codesandbox
Note : If you import all icons using * , you're importing hundreds of icons at once which is probably not ideal.
I am learning Svg using React. I have form input which brings me the order number of inside . I mean the user will enter a number to my form input and I will sort my which has element according to that number. I tried index as a style but it does not work. I researched it before. SVG does not support z-index. In this state what should I do? Do you have any recommendations for me? By the way, I am using g inside SVG because I will use it for drag and drop.
I call my component with this code :
<div ref={takeRef} className="center">
<svg>
{state.dragFrames.map((d, i) => (
<Frame
key={d.id}
data={d}
onDrag={onDrag}
onDragStop={onDragStop}
/>
))}
</svg>
</div>
My Frame component :
import React, { useEffect, useState} from "react";
import { DraggableCore } from "react-draggable";
const Frame = React.memo(function Frame(props: any) {
const render = () => {
const { z,width,height } = props.data;
return (
<DraggableCore onStart={onStart} onDrag={onDraggingFrame} onStop={onDragStop}>
<g className="confine" style={{zIndex:z}} >
<rect
cursor="grab"
width={width}
height={height}
>
</rect>
</g>
</DraggableCore>
)
}
return (
<>
{render()}
</>
)
}
)
export default Frame;
I am trying to use functional components with hooks in React. I've used plenty of class components, but it seems like functional components are the new pattern for React, so I'm trying to make them work.
What I am trying to do is modify an SVG file I am loading when the user does something.
Here's the basics of my code:
function home() {
const appleRef = useRef({ value: null });
useEffect(() => {
if (typeof appleRef !== "undefined") {
console.log(appleRef);
}
}, []);
return(
<DiApple
ref={appleRef}
size={"3rem"}
color={"black"}
className="mi-home-card-icon mi-home-card-icon-apple"
/>
)
}
Which turns into this in the DOM:
<svg stroke="currentColor" fill="currentColor" stroke-width="0" version="1.1" viewBox="0 0 32 32" color="black" class="mi-home-card-icon mi-home-card-icon-apple" height="3rem" width="3rem" xmlns="http://www.w3.org/2000/svg" style="color: black;"><path d="M23.023 17.093c-0.033-3.259 2.657-4.822 2.777-4.901-1.512-2.211-3.867-2.514-4.705-2.548-2.002-0.204-3.91 1.18-4.926 1.18-1.014 0-2.583-1.15-4.244-1.121-2.185 0.033-4.199 1.271-5.323 3.227-2.269 3.936-0.58 9.769 1.631 12.963 1.081 1.561 2.37 3.318 4.061 3.254 1.63-0.064 2.245-1.055 4.215-1.055s2.524 1.055 4.248 1.021c1.753-0.032 2.864-1.591 3.936-3.159 1.24-1.814 1.751-3.57 1.782-3.659-0.038-0.017-3.416-1.312-3.451-5.202zM19.783 7.53c0.897-1.089 1.504-2.602 1.34-4.108-1.294 0.053-2.861 0.86-3.79 1.948-0.832 0.965-1.561 2.502-1.365 3.981 1.444 0.112 2.916-0.734 3.816-1.821z"></path></svg>
I want to be able to modify this SVG information on the user interacting with certain other DOM elements.
When I try to use this, I get the error:
Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
Which from what I'm reading, I need to also add a forwardRef, because React needs it to be a component for some reason?
I'm not totally understanding the exact process here.
If someone could explain to me what my code should look like to be able to affect the SVG, as well as what exactly forwardRef is doing here and how it differs from class components, that would be massively helpful to me.
import React, { useEffect, useRef } from "react";
function Home() {
const appleRef = useRef({ value: null });//remove this ref
const svgRef = React.createRef();
const DiApple = React.forwardRef((props, ref) => {
return (
<svg
ref={ref}
stroke="currentColor"
fill="currentColor"
strokeWidth="0"
version="1.1"
viewBox="0 0 32 32"
color="black"
className="mi-home-card-icon mi-home-card-icon-apple"
height="3rem"
width="3rem"
xmlns="http://www.w3.org/2000/svg"
style={{ color: "black" }}
{...props}
>
<path d="M23.023 17.093c-0.033-3.259 2.657-4.822 2.777-4.901-1.512-2.211-3.867- 2.514-4.705-2.548-2.002-0.204-3.91 1.18-4.926 1.18-1.014 0-2.583-1.15-4.244-1.121-2.185 0.033-4.199 1.271-5.323 3.227-2.269 3.936-0.58 9.769 1.631 12.963 1.081 1.561 2.37 3.318 4.061 3.254 1.63-0.064 2.245-1.055 4.215-1.055s2.524 1.055 4.248 1.021c1.753-0.032 2.864-1.591 3.936-3.159 1.24-1.814 1.751-3.57 1.782-3.659-0.038-0.017-3.416-1.312-3.451-5.202zM19.783 7.53c0.897-1.089 1.504-2.602 1.34-4.108-1.294 0.053-2.861 0.86-3.79 1.948-0.832 0.965-1.561 2.502-1.365 3.981 1.444 0.112 2.916-0.734 3.816-1.821z"></path>
</svg>
);
});
return (
<DiApple
ref={svgRef}
size={"3rem"}
color={"black"}
className="mi-home-card-icon mi-home-card-icon-apple"
/>
);}
export default Home;
reference to svg is avaliable on the ref object created using React.createRef as follows svgRef.current
DiApple is a function component, and as explained in React documentation about forwarding refs, to define what ref will refer to on DiApple, you need to wrap it in a forwardRef call and pass the ref argument to your desired element:
const DiApple = React.forwardRef(function DiApple(props, ref) {
return (
<svg ref={ref}>
{/* ... */}
</svg>
)
})
Next, I suggest passing null to useRef instead of { value: null }, that way appleRef.current will initially be null, then it will refer to the DOM node:
const appleRef = useRef(null);
useEffect(() => {
if (appleRef.current !== null) {
console.log(appleRef.current);
}
}, []);
I recommend reading more about useRef.
Hello when I want to render an array Polygon inside SVG is works only when the component is defined inside the Component:
This works:
function Polygons() {
const Polygon1 = ({ points, key }) => {
return <polygon key={key} stroke="blue" points={points} />;
};
const [polygons, setPolygons] = useState([]);
return (
<div className="App">
<div>
<svg width="500px" height="500px" version="1.1">
{polygons.map((polygon, i) => {
return <Polygon1 key={`polygon-${i}`} points={polygon.points} />;
})}
</svg>
</div>
<button
onClick={() => {
setPolygons([...polygons, { points: [10, 10] }]);
}}
>
Add Polygon
</button>
<button
onClick={() => {
if (!polygons.length) {
alert("Please add first Polygon");
return;
}
const lastPolygon = Object.assign({}, polygons[polygons.length - 1]);
lastPolygon.points.push([Math.random() * 500, Math.random() * 500]);
const newPolygons = [...polygons];
newPolygons[newPolygons.length - 1] = lastPolygon;
setPolygons(newPolygons);
}}
>
Add Point
</button>
</div>
);
}
and this does not work:
const Polygon1 = ({ points, key }) => {
return <polygon key={key} stroke="blue" points={points} />;
};
function Polygons() {
const [polygons, setPolygons] = useState([]);
return (
<div className="App">
<div>
<svg width="500px" height="500px" version="1.1">
....
Can somebody explain me this behaviour and how can I solve this problem? I dont want to define the component inside another component.
I created a codesandbox, so you see the problem: Codesandbox
I'm trying to add a clickable image to close a material-ui dialog.
The props.onRequestClose works properly when I click outside the dialog but the onClick doesn't response.
What am I missing?
const ChangePasswordDialog = (props) => (
<Dialog open={props.open} onRequestClose={props.onRequestClose} modal={false}>
<div className="close-popup">
<Svg onClick={props.onRequestClose} viewBox="0 0 22.75 22.75">{closePopup}
</Svg >
</div>
</Dialog>
);
ChangePasswordDialog.propTypes = {
open:PropTypes.bool.isRequired,
onRequestClose:PropTypes.func.isRequired
};
I solved it by adding a prop called onClick to the Svg components.
Here is the code for the Svg components if someone needs:
class Svg extends Component{
render() {
const {children, viewBox, onClick} = this.props;
return(
<div onClick={onClick}>
<SvgIcon viewBox={viewBox}>
{children}
</SvgIcon>
</div>
)
};
}
Svg.propTypes = {
children:PropTypes.any.isRequired,
viewBox:PropTypes.string,
onClick:PropTypes.function
};
export default Svg;