So the last post was establishing that... I was creating a real time theatrical experience. We will start simple... creating a simple timer, as I mentioned the most pivotal part of keeping a show running is the SM's control of timing. So starting with a shared clock is important, actors will know where they are, cues will be on a standby and hopefully everything flows together.
After we go through the process of establishing how to set the timer, I will discuss how that syncs with everyone but will get into that code another time.
So setInterval is an easy function with a callback and then a delay in milliseconds. Say you want to say hi every second (I have young nieces and nephews so I have experienced such a thing in real life).
setInterval(()=>{console.log("Hi")},1000)
So there is an anonymous function at the start and it triggers every 1000 milliseconds. Great easy enough. Not so fast... well one second to be exact. This will keep happening and can cause a memory leak due to the fact that function may continuously run in the background.
To fix that up you can assign the interval to a variable name.
let myInterval = setInterval(()=>{console.log("Hi")},1000)
Setting it to a variable will still start the interval, to stop it all you have to do is clearInterval(myInterval) and it will stop.
Fun thing to note if you console.log(myInterval) it is a number kept as a reference to enable cleanup. You may have many timers going on a page, so it is important to have them accessible.
Alright now that the basic rules have been established let's talk about the timer. Easy transition,
let time = 0
let countUp = setInterval(()=>{timer +=1}, 1000)
This will go up every second, if you clearInterval(countUp) the time will remain the same but you can then create another countUp just by running the line countUp
.
React adds a whole different layer of complexity to something like this. Due to re-renders you could accidentally double up on a timer. That's not good when you're trying to keep consistency among remote browsers.
So to do this you add some logic to mounting and unmounting (really why don't they call this dismount? always has bothered me). State travels along with re-renders, so you can add a value of clockRunning, and set it to true or false based upon what is happening. We will do this is a functional component for now.
import react, {useEffect, useState} from 'react'
function Counter(props) {
let [time, setTime] = useState(0)
let [clockRunning, setClockRunning]= useState(false)
let myInterval
clearInterval(myInterval)
useEffect(()=>{
if (clockRunning){
myInterval = (setInterval(() => { setTime(time += 1) }, 1000))
}
return ()=> clearInterval(myInterval)},[clockRunning]
)
return (
<>
<button onClick={()=>setClockRunning(true)}>
Count up
</button>
<div>
{time}
</div>
<button onClick={()=>setClockRunning(false)}>
Stop
</button>
</>
)
}
export default Counter
So here the we clean up the interval on render just in case. It doesn't cost us anything but is a nice safeguard to have. We are defaulting the clock to not run on first render but our buttons can change that. In our useEffect, it runs every time counting changes. The return on the bottom is the clearing of the interval on a rerender, however since we are starting a new interval on render if clockRunning is true, we don't lose anything.
This isn't fancy by any means but this is the basis of a lot of running a show. This information and more will travel over Websockets so everyone has the same experience. The timer, however, is kept on the server. That is a huge part of this trick. We were worried about the stage managers computer crashing or they lost internet connection so we needed to figure out a way to communicate all this information. By keeping the timer on the server and communicating through websockets, if you are logged in to the site, that means you have access to the timer. More on that another time though. We are beginning to build our show control though!
Top comments (0)