next.js js:如何等待第一次渲染使用document.getElementById()?

ssgvzors  于 2023-04-20  发布在  其他
关注(0)|答案(1)|浏览(180)

我有一个通过id访问canvas元素的脚本。它基于this tutorial。他使用普通的JavaScript并在大约5:10解释了他的方法。我推断到下面的next.js。

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>
    )
}

如果没有useEffect,这会失败--我相信是因为document.getElementById在元素呈现之前运行。我找到了几个解决方案,包括创建一个custom hook,但useEffect似乎是最优雅的。
这是react的使用方式吗?这是我的if "__name__" == "__main__"从Python,但防止在第一次渲染时运行?自定义钩子是首选方法吗?谢谢你提前提出的见解。

nvbavucw

nvbavucw1#

是的,useEffect适合处理函数式React组件中的DOM交互,因为它允许在渲染后运行副作用
你是对的,你尝试通过id访问canvas元素,在组件渲染之前不可用。使用带有空依赖数组**[]**的useEffect,你告诉React在初始渲染后运行一次效果,类似于类组件中的componentDidMount生命周期方法。
使用自定义钩子是抽象这种逻辑的另一种方法,使代码模块化和可重用。然而,自定义钩子仍然需要在内部使用useEffect来处理相同的问题。
此外,你可以使用React的useRef来获取对canvas元素的引用,而无需直接访问DOM。下面是一个如何更新代码的示例:

import React, { useEffect, useRef } from 'react';

export default function Simulator() {
const canvasRef = useRef(null);

useEffect(() => {
    if (canvasRef.current) {
        const canvas = canvasRef.current;
        const c = canvas.getContext("2d");

        // rest of your code
    }
}, [])

return (
    <div className="mt-10">
        <canvas ref={canvasRef} className="border-2"></canvas>
    </div>)
}

这种使用useRef的方法更“类似于React”,因为它避免了使用document.getElementById直接与DOM交互,而是依赖于React的内置功能。

相关问题