Home > Back-end >  How to add an SVG circle to an Array of SVGs in react on button click
How to add an SVG circle to an Array of SVGs in react on button click

Time:12-03

import { useState, useRef } from 'react'
import './App.css'

function App() {
  const [circle, setCircle] = useState([])
  const refElement = useRef(null);

  const width = 500;
  const height = 500;
  const circleX= Math.floor(Math.random() * 400);
  const circleY = Math.floor(Math.random() * 400);
  const circleRadius = 20;
  const randomColor = '#'   (Math.random().toString(16)   "000000").substring(2,8)

  const LeadCircle = <circle cx={circleX} cy={circleY} r={circleRadius} fill={randomColor} stroke={"black"} strokeWidth={"10"}/>
  const Circle =  <circle cx={circleX} cy={circleY} r={circleRadius} fill={randomColor}/>


  const addLead = () =>{
    console.log("circleLead added "   LeadCircle)
    LeadCircle
    setCircle(previous =>[...circle,previous]);

  }

  const addNormal = () =>{
    console.log("circleNormal added "   Circle)
  }
  
  const removeLast = () =>{
    
  }
  const removeAll = () =>{
    
  }


  return (
    <div className="App">
      <h1>doobverse setup with svg</h1>
      <div className="card">
      <div id="svg-container">
        <svg width={width} height={height} style={{border:"2px solid white"}} useref={refElement}> 
        {LeadCircle}
        </svg>
      </div>
        <br></br>
        <br></br>
        <button id={"addLead"} onClick={addLead}>
          Add lead
        </button>
        <button onClick={addNormal}>
          Add normal
        </button>
        <br></br><br></br>
        <button onClick={removeLast}>
          remove one
        </button>
        <button onClick={removeAll}>
          remove all
        </button>
      </div>
    </div>
  )
}

export default App

So thats my Code,

I just want to have a simple React app, where you can add a circle on button click, remove the last drawn circle, and remove all drawn circles... Ive tried to do this with canvas before. I could draw circles on click but had Problems removing them, so I have asked in a Discord where they explained me that you need to clear and redraw the canvas every time you want to remove an element and that its easier to work with svgs, so I've set the thing up with svgs but now its not even working with the add function...

Thx for help !!

:)

CodePudding user response:

To add a circle to an array of SVGs in React, you can use the useState hook to store the array of circles and the useRef hook to reference the SVG element in your component. Then, you can create a new circle element and add it to the array of circles using the setCircle function. Here's an example of how you can do this:

import { useState, useRef } from 'react'

function App() {
  const [circles, setCircles] = useState([])
  const svgRef = useRef(null)

  const width = 500
  const height = 500
  const circleX = Math.floor(Math.random() * 400)
  const circleY = Math.floor(Math.random() * 400)
  const circleRadius = 20
  const randomColor = '#'   (Math.random().toString(16)   "000000").substring(2,8)

  const addCircle = () => {
    // Create a new circle element
    const circle = (
      <circle
        cx={circleX}
        cy={circleY}
        r={circleRadius}
        fill={randomColor}
        stroke={"black"}
        strokeWidth={"10"}
      />
    )

    // Add the circle to the array of circles
    setCircles(prevCircles => [...prevCircles, circle])
  }

  return (
    <div>
      <h1>doobverse setup with svg</h1>
      <div className="card">
        <div id="svg-container">
          {/* Reference the SVG element using the useRef hook */}
          <svg width={width} height={height} style={{border:"2px solid white"}} ref={svgRef}>
            {/* Render the array of circles */}
            {circles.map(circle => circle)}
          </svg>
        </div>
        <br />
        <br />
        {/* Add a new circle when the button is clicked */}
        <button onClick={addCircle}>Add circle</button>
      </div>
    </div>
  )
}

export default App

In this example, the addCircle function is called when the "Add circle" button is clicked, and it creates a new circle element with random position and color. It then adds this element to the array of circles using the setCircles function. The array of circles is rendered inside the SVG element by mapping over the array and rendering each circle element.

CodePudding user response:

It looks like you're trying to create an SVG circle element using the LeadCircle and Circle variables and add it to the circle state array when the addLead or addNormal functions are called. However, there are a few issues with your code that are preventing this from working correctly.

First, in the addLead function, you are calling the LeadCircle variable, which contains an SVG circle element, but you are not actually adding it to the circle state array. Instead, you are adding the previous value of the circle array to itself using the spread operator (...), which will not have the desired effect. To fix this, you should replace the line setCircle(previous =>[...circle,previous]); with setCircle(previous =>[...previous, LeadCircle]);. This will add the LeadCircle element to the circle array and update the state.

Next, you are using the useRef hook to create a reference to an SVG element, but you are not actually using this reference in your code. In the addLead and addNormal functions, you need to use this reference to add the LeadCircle and Circle elements to the SVG element. You can do this by calling the current property of the refElement variable and using the appendChild method to add the elements to the SVG element. For example, you could add the following line to the addLead function:

refElement.current.appendChild(LeadCircle);

Finally, you are not rendering the circle state array in the SVG element, so the circles that you add will not be visible on the page. To fix this, you can use the map method to iterate over the circle array and render each element in the SVG element. For example, you could replace the line {LeadCircle} with the following:

{circle.map(circle => circle)}

This will render each element in the circle array in the SVG element.

  • Related