skip to Main Content

I’m trying to make a web app that just shoots up a bunch of fireworks once a button is pressed.
It’s in react and I’m trying to use the useEffect hook to make the fireworks shoot up once the ID variable is updated.
When it renders in the beginning, it works just fine, it shoots up fireworks how I want it to, but the restart button doesn’t work. No fireworks are shown after the first time.
By using console.log, I’ve made sure that the useEffect block is actually being called when the button is pressed and the count changes. I think what is happening is because the container gets declared again, it’s not updating when it rerenders? I honestly have no clue, would really appreciate some help <3

import './App.css';
import React from 'react';
import {useEffect, useState} from 'react';
import Fireworks from 'fireworks-js';

function App() {

  const delay = ms => new Promise(res => setTimeout(res, ms))

  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count+1)
    console.log('button pressed' + count);
  }

  useEffect(()=>{
    console.log('effect called' + count);
    const container = document.getElementById('fireworks-container');
    const fireworks = new Fireworks(container);
    fireworks.launch(10);
    fireworks.launch(20);
    makeRequest();

    async function makeRequest() {
      await delay(200);
      fireworks.launch(20);
      await delay(300);
      fireworks.launch(20);
    }
  }, [count]);

  return (
    <div className="App">
      <h1 className = "text">Fireworks App</h1>
      <button onClick={handleClick}>Restart</button>
      <div id = 'fireworks-container' style = {{width: '100%', height: '100vh'}}/>
    </div>
  );
}

export default App;

I was expecting that the fireworks would just appear again since I make a new firework and launch it? I feel like I need to make the firework object outside of the useEffect, but it doesn’t work and gives me a bunch of errors.

2

Answers


  1. Chosen as BEST ANSWER

    I tried what @Caleth suggested in the comments, and it also ended up working, so I will post it here. I made two separate useEffect blocks, where one just initializes the container and the firework object! Thanks everyone for your help!

    import './App.css';
    import React, { useRef } from 'react';
    import {useEffect, useState} from 'react';
    import Fireworks from 'fireworks-js';
    
    function App() {
    
      const delay = ms => new Promise(res => setTimeout(res, ms))
    
      const fireworks = useRef();
    
      useEffect(()=>{
        const container = document.getElementById('fireworks-container');
        fireworks.current = new Fireworks(container);
      }, []);
    
      const [count, setCount] = useState(0);
    
      function handleClick() {
        setCount(count+1)
        console.log('button pressed' + count);
      }
    
      useEffect(()=>{
        console.log('effect called' + count);
        fireworks.current.launch(10);
        fireworks.current.launch(20);
        makeRequest();
    
        async function makeRequest() {
          await delay(200);
          fireworks.current.launch(20);
          await delay(300);
          fireworks.current.launch(20);
        }
      }, [count]);
    
      return (
        <div className="App">
          <h1 className = "text">Fireworks App</h1>
          <button onClick={handleClick}>Restart</button>
          <div id = 'fireworks-container' style = {{width: '100%', height: '100vh'}}/>
        </div>
      );
    }
    
    export default App;


  2. The issue lies in the way the Fireworks library is being used within the useEffect hook. Since the fireworks instance is not being properly reset or destroyed, it may cause unexpected behavior when the useEffect hook is triggered again.

    To resolve this issue, you can store the fireworks instance in a useRef hook and update it when the useEffect hook is triggered. Here’s an updated version of your code that should address the problem:

    import React, { useEffect, useState, useRef } from 'react';
    import Fireworks from 'fireworks-js';
    
    function App() {
      const delay = ms => new Promise(res => setTimeout(res, ms));
      const [count, setCount] = useState(0);
      const fireworksRef = useRef(null);
    
      function handleClick() {
        setCount(count + 1);
        console.log('button pressed: ' + count);
      }
    
      useEffect(() => {
        console.log('effect called: ' + count);
    
        if (!fireworksRef.current) {
          const container = document.getElementById('fireworks-container');
          fireworksRef.current = new Fireworks(container);
        }
    
        const fireworks = fireworksRef.current;
        fireworks.launch(10);
        fireworks.launch(20);
        makeRequest();
    
        async function makeRequest() {
          await delay(200);
          fireworks.launch(20);
          await delay(300);
          fireworks.launch(20);
        }
    
        return () => {
          fireworks.stop(); // Stop the fireworks when the component unmounts
        };
      }, [count]);
    
      return (
        <div className="App">
          <h1 className="text">Fireworks App</h1>
          <button onClick={handleClick}>Restart</button>
          <div id="fireworks-container" style={{ width: '100%', height: '100vh' }} />
        </div>
      );
    }
    
    export default App;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search