skip to Main Content

I’m making a React application involving SVG’s which react to mouseclicks. Every time the user clicks on the screen, the SVG will morph and point to the click position.

The SVG also has an tag within it which is supposed to excecute an animation 1 time.

Ideally, this animations should execute once every time the mouse is clicked. However I am finding that it only executes on the first mouse click. The subsequent clicks do not have an effect.

I am guessing this is happening because the tag is rendered once onto the DOM and it just stays there.

Ideally I would like it to destroy that element, and render a fresh one each time the mouse is clicked.

How do you do this in React?

Here is an outline of my code.

 function Drawing(inp){

    var [startPosLocal, set_startPosLocal] = useState(inp.startPos);
    var [destPosLocal, set_destPosLocal] = useState(inp.destPos);
    

    let pathString = createRayPathString(inp.startPoint, inp.endPoint);
 



    return(
        <g>
            <path d={pathString} stroke="blue" stroke-width="2" >

                {/*This is the element that I want destroyed and rendered  on each click*/}
                <animate dur="1s" values"0; 1;" repeatCount="1" />
                

            </path>

        </g>
    )


}

Note that I have created 2 state variables to represent the mouse start and destination positions however they are not currently in use. I have tried inputting these state variables into the animate tag (thinking that state variables will trigger re-renders) but it didn’t work.

2

Answers


  1. You can try removing the animate element (or the g element if it does not work) for a render and adding it again.

    var [removeAnimate, set_removeAnimate] = useState(false);
    
    useEffect(() => {
       if (removeAnimate)
           set_removeAnimate(false)
    }, [set_removeAnimate])
    
    useEffect(() => {
       set_removeAnimate(true)
    }, [props.clickedPosition])
    

    {!removeAnimate && <animate ...}
    

    or

    return removeAnimate ? null : <g ...
    
    Login or Signup to reply.
  2. I’ve tried a similar solution suggested by palindrom but i added a key prop to my svg and it’s working.

    function Drawing() {
      const [isAnimating, setIsAnimating] = useState(true)
      const [animationKey, setAnimationKey] = useState(0)
    
      const handleClick = () => {
        setIsAnimating(true)
        setAnimationKey((prev) => prev + 1)
      }
    
      const d = `M ${0} ${0} L ${6} ${400}`
    
      return (
        <>
          <button onClick={handleClick}>Hello World</button>
    
      <svg key={animationKey}>
        <g>
          <path d={d} stroke="blue" stroke-width="7">
            {isAnimating && (
              <animateTransform
                attributeName="transform"
                type="rotate"
                from="0 50 50"
                to="360 50 50"
                dur="1s"
                fill="freeze"
                onAnimationEnd={() => setIsAnimating(false)}
              />
            )}
          </path>
        </g>
      </svg>
    </>
    

    )
    }

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search