skip to Main Content

js code keeps running even if element is removed from page.
first difficulty when coding with react-js. because the page is not reloaded so the initial script is still running, like setInterval,websocket,etc code. simple example below element has been removed but still running. not effective if i have to create with global variable

<button onclick="createNewJsCode()">create new js</button>
<button onclick="removeJsCode()">remove js</button>
<script>
  let id = ''
  function createNewJsCode(){
    let s = document.createElement('script')
    let code = 'setInterval(`console.log(new Date())`,500)'
    s.id = (id = crypto.randomUUID())
    s.appendChild(document.createTextNode(code));
    document.body.appendChild(s);
  }
  function removeJsCode(){
    document.getElementById(id).remove()
  }
</script>

2

Answers


  1. You can’t just remove the <script> node, you have to do a little more specific cleanup.

    setInterval returns an interval ID that you can pass to clearInterval to stop it.

    Generally, I’d say your code does not make a whole lot of sense in a React context, but in your case you could do something like this:

    <button onclick="createNewJsCode()">create new js</button>
    <button onclick="removeJsCode()">remove js</button>
    <script>
      let id;
      let intervalId;
      function createNewJsCode(){
        let s = document.createElement('script')
        let code = 'intervalId = setInterval(`console.log(new Date())`,500)'
        s.id = (id = crypto.randomUUID())
        s.appendChild(document.createTextNode(code));
        document.body.appendChild(s);
      }
      function removeJsCode(){
        clearInterval(intervalId);
        document.getElementById(id).remove()
      }
    </script>
    Login or Signup to reply.
  2. Seen as this is a React question, below is an example of using a setInterval inside a React Component. If your using some form of React Router the below code will also correctly unmount / mount etc.

    const {useState, useEffect} = React;
    
    function Page() {
      const [counter, setCounter] = useState(0);
      useEffect(() => {
        const i = setInterval(() => {
           console.log(new Date());
           setCounter(c => c +1);
        }, 1000);
        return () => {
          console.log('umount');
          clearInterval(i);
        }
      }, []);
      return <div>
        This is a page, and when unmounted will end the setInterval. <br/>Counter: {counter}, time: {new Date().toLocaleString()}<br/> Check console you will also see console logging of datetime finishes.
      </div>
    }
    
    function OtherInfo() {
      return <div>
        Notice how the timer stopped inside the console.  <br/>  If you click Show Page the component will be mounted again, this is kind of the basis of how React Router works in a Single Page Application (SPA).
      </div>
    }
    
    function App() {
      const [pageVis, setPageVis] = useState(true);
      return <div>
        {pageVis && <Page/>}
        {!pageVis && <OtherInfo/>}
        <hr/>
        {pageVis && <button onClick={() => setPageVis(false)}>Unmount Page</button>}
        {!pageVis && <button onClick={() => setPageVis(true)}>Show Page</button>}
      </div>
    }
    
    
    const root = ReactDOM.createRoot(document.querySelector('#mount'));
    root.render(<App/>);
    <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    
    <div id="mount"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search