I was putting together some code to demonstrate how modifying a state variable causes a component to rerender. All was going will until I put a timer on the component, that got the current and displayed it in the page. That worked fine example 1, but it all changed when I wanted to keep a list of all the times and print them all out each time a new time was added, things a got a little weird, example 2.
Example 1.
Get the time and continually display it
import React, { useState } from 'react' import { useEffect } from 'react'; function getTheTime() { let currentDate = new Date(); let currentTime = currentDate.getHours() + ":" + currentDate.getMinutes() + ":" + currentDate.getSeconds(); return currentTime; } export default function FCDisplayTimeInSameSpot(){ console.log("Executing FCDisplayTimeInSameSpot()"); const [containerState, setContainerState] = useState(["<NO TIME SET>"]); const getDisplayData = () => { const cdata = containerState return cdata; } // This useEffect will only run once when the component is first mounted useEffect(()=>{ setInterval(()=>{ setContainerState(getTheTime()); }, 30000); }, []) // This useEffect will run every time the component re-renders useEffect(() =>{ console.log(getDisplayData()) }) // This useEffect will only run once when the component is first mounted useEffect(() =>{ console.log("mounting the FCDisplayTimeInSameSpot"); }, []); // This useEffect will run every time the component is unmounted useEffect(() =>{ return ()=>console.log("unmounting the FCDisplayTimeInSameSpot"); }); return ( <> <p>Time is - {getDisplayData()}</p> </> ) }
Drop this component as a child of any other component to see it work e.g.
import React from 'react'; import './App.css'; import FCDisplayTimeInSameSpot from './FCDisplayTimeInSameSpot'; function App() { const switchComponents = true; return ( <div className="App"> <header className="App-header"> <FCDisplayTimeInSameSpot/> </header> </div> ); } export default App;
Monitor the behaviour from the outputs in the browser’s console, you will notice the following
Event | What’s executed in order shown |
---|---|
Initial loading of the component Notice that both these useEffects() witht the lambda and empty array are called once and only once |
// This useEffect will only run once when the component is first mounted useEffect(()=>{ setInterval(()=>{ setContainerState(getTheTime()); }, 10000); }, []) // This useEffect will only run once when the component is first mounted useEffect(() =>{ console.log("mounting the FCDisplayTimeInSameSpot"); }, []); |
Component needs to be re-rendered Notice that the component method is first called, then it is unmounted, then is finally re-rendered through the component return() block (you can see this because the useEffect() with only the lambda is called |
// This useEffect will run every time the component is unmounted useEffect(() =>{ return ()=>console.log("unmounting the FCDisplayTimeInSameSpot"); }); // This useEffect will run every time the component re-renders useEffect(() =>{ console.log(getDisplayData()) }) |
Notice that the component method is always called