使用useffect()复制componentDidMount逻辑以在客户端加载外部JavaScript

使用useffect()复制componentDidMount逻辑以在客户端加载外部JavaScript,javascript,reactjs,next.js,Javascript,Reactjs,Next.js,我正在一个NextJS项目中实现一个富文本编辑器。它没有React组件,并且只在客户端运行,因此我必须从外部源加载JavaScript和CSS文件,并处理SSR。请不要建议使用其他工具,因为这不是一个选项 该工具作为类组件运行良好,但我想将其移植到功能组件中。当我测试功能组件时,它偶尔会工作——也就是说,在我更改文件并保存之后(即使只是添加了一个空间)。但只要我刷新页面,我就失去了编辑器。我以为这是因为组件没有安装,但现在我检查了一下,问题仍然存在 我尝试过各种方法,包括禁用SSR的Next动态

我正在一个NextJS项目中实现一个富文本编辑器。它没有React组件,并且只在客户端运行,因此我必须从外部源加载JavaScript和CSS文件,并处理SSR。请不要建议使用其他工具,因为这不是一个选项

该工具作为类组件运行良好,但我想将其移植到功能组件中。当我测试功能组件时,它偶尔会工作——也就是说,在我更改文件并保存之后(即使只是添加了一个空间)。但只要我刷新页面,我就失去了编辑器。我以为这是因为组件没有安装,但现在我检查了一下,问题仍然存在

我尝试过各种方法,包括禁用SSR的Next动态导入,但到目前为止,只有下面的类方法起作用(编辑器通过绑定到
元素来工作):

从“React”导入React;
从“./组件/布局”导入布局;
类页扩展了React.Component{
state={isServer:true};
componentDidMount(){
this.MyEditor=require(“../public/static/cool editor.js”);
this.setState({isServer:false});//触发器重新启动程序。
var app=MyEditor(“entry”);//创建editor的实例。
}
渲染(道具){
返回(
);
}
}
导出默认页面;
最后一次尝试功能组件:

import React, { useEffect } from "react";
import Layout from "../components/Layout";

function hasWindow() {
  const [isWindow, setIsWindow] = React.useState(false);

  React.useEffect(() => {
    setIsWindow(true);
    return () => setIsWindow(false);
  }, []);

  return isWindow;
}

const Editor = () => {
  useEffect(() => {
    const script = document.createElement("script");
    script.src =
      "http://localhost:3000/static/article-editor/cool-editor.js";
    script.async = true;
    document.body.appendChild(script);
    return () => {
      document.body.removeChild(script);
    };
  }, []);

  var app = MyEditor("entry");

  return (
    <Layout>
      <textarea id="entry"></textarea>
    </Layout>
  );
};

const Page = () => {
  const isWindow = hasWindow();

  if (isWindow) return <Editor />;

  return null;
};
export default Page;
import React,{useffect}来自“React”;
从“./组件/布局”导入布局;
函数hasWindow(){
const[isWindow,setIsWindow]=React.useState(false);
React.useffect(()=>{
setIsWindow(真);
return()=>setIsWindow(false);
}, []);
返回窗口;
}
常量编辑器=()=>{
useffect(()=>{
常量脚本=document.createElement(“脚本”);
script.src=
"http://localhost:3000/static/article-编辑器/cool editor.js”;
script.async=true;
document.body.appendChild(脚本);
return()=>{
document.body.removeChild(脚本);
};
}, []);
var app=MyEdit(“条目”);
返回(
);
};
常量页=()=>{
常量isWindow=hasWindow();
如果(isWindow)返回;
返回null;
};
导出默认页面;

您可以在
标记中使用
useRef
挂钩:

const refContainer = useRef(null);

return <textarea ref={refContainer}>

检查此处的代码:

我可以建议更改的一些内容:

  • var-app=MyEditor(“条目”)。考虑使用<代码> USERFE/COD>作为保持实例变量的方式:
  • Editor
    中,未定义
    MyEditor
    变量
  • hasWindow
    包含一个运行一次的
    useffect
    (使用空的依赖项数组),我认为它不需要清理功能。要检查是否停留在浏览器或服务器上,只需使用
    const isServer=type of window===“undefined”
  • 自定义挂钩应使用前缀
    use

您能否提供一个最小的可复制示例?
const refContainer = useRef(null);

return <textarea ref={refContainer}>
  useEffect(() => {
    if (refContainer.current) {
      refContainer.current.innerHTML = "ref has been mounted";
      console.log("hello");
    }
  }, []);