I am starting with React and trying to make a dynamic svg: I'd like to 'bind' the numeric value of the input to the number of circles (<use>
) shown on the canvas. However, the {message}
state variable does not work in a for
loop – I don't know how to create/modify the array. How could I render the {sampleCircles}
dynamically? Thanks in advance.
import { useState } from "react";
export default function Svg() {
const [message, setMessage] = useState(0);
let sampleCircleCopies = [
<use href="#originalCircle" x="15" y="15" key="1" />,
<use href="#originalCircle" x="30" y="30" key="2" />
];
const handleChange = (event) => {
setMessage(event.target.value);
};
return (
<>
<svg className="p-0 border-2 mx-auto" width="400" height="400">
<circle
cx="50%"
cy="50%"
r="10"
id="originalCircle"
style={{ fill: "orange" }}
/>
{sampleCircleCopies}
</svg>
<div>
<input
type="number"
className="border-2 mt-2 p-1 rounded-xl"
onChange={handleChange}
value={message}
/>
<h2>Number of cloned circles: {message}</h2>
</div>
</>
);
}
CodePudding user response:
You can use map()
to create an array of JSX elements which react will render for you. I'd also use valueAsNumber
instead of value
. You can of course also embed the map()
directly within the JSX.
function Svg() {
const [message, setMessage] = React.useState(0);
const sampleCircleCopies = [...new Array(message)].map((_, i) => (
<use href="#originalCircle" x={Math.floor(200 * Math.random())} y={Math.floor(50 * Math.random())} key={i} />
));
const handleChange = (event) => {
setMessage(event.target.valueAsNumber);
};
return (
<React.Fragment>
<svg className="p-0 border-2 mx-auto" width="400" height="400">
<circle
cx="50%"
cy="50%"
r="10"
id="originalCircle"
style={{ fill: "orange" }}
/>
{sampleCircleCopies}
</svg>
<div>
<input
type="number"
className="border-2 mt-2 p-1 rounded-xl"
onChange={e => handleChange(e)}
value={message}
/>
<h2>Number of cloned circles: {sampleCircleCopies.length}</h2>
</div>
</React.Fragment>
);
}
ReactDOM.render(<Svg/>, document.getElementById('root'));
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<div id="root"></div>
I've changed the code a bit to generate random circles every time the count increases in order to show that the code is working and you are getting however many circles you want.