next.js: How to wait for a first render to use document.getElementById()?

I have a script that accesses a canvas element by id. It is based on this tutorial. He uses plain JavaScript and explains his method at about 5:10. I extrapolated to next.js below.

import React, { useEffect } from 'react';

export default function Simulator() {
    useEffect(() => {
        var canvas = document.getElementById("myCanvas");
        var c = canvas.getContext("2d");

        //deleted for simplicity, but similar code to his is below...
        
    }, [])
    
    return (
        <div className="mt-10">
            <canvas id="myCanvas" className="border-2"></canvas>
        </div>
    )
}

This fails without useEffect–I believe because document.getElementById is run before the element is rendered. I found several solutions, including making a custom hook, but useEffect appears to be the most elegant.

Is this how react is meant to be used? Is this my if "__name__" == "__main__" from Python but to guard against running on first render? Is the custom hook the preferred method? Thank you for your insights in advance.