Closed

Description
描述问题
react hook中使用Vditor时,出现以下问题:
代码:
import React,{ useRef } from 'react'
import Vditor from 'vditor'
const Markdown = () => {
let editor = useRef(null)
let vditor = new Vditor(editor, {
height: 360,
toolbarConfig: {
pin: true
},
cache: {
enable: false
},
after() {
vditor.setValue('Hello, Vditor + React!')
}
})
return (
<div ref={editor} />
)
}
export default Markdown
控制台报错:
Uncaught (in promise) TypeError: Cannot add property innerHTML, object is not extensible
at initUI (index.min.js:6245)
at index.min.js:15342
期待的结果
能否出一个简单的react hook使用示例代码
版本信息
- 版本:3.8.5
- 操作系统:macOS 11.2
- 浏览器:google 92.0
Activity
BeiyanYunyi commentedon Sep 13, 2021
我用 id 还行,ref 可能并不是一个 element。JSX.Element 和 DOM 的 Element 应该还是有差别的。
ghost commentedon Sep 14, 2021
BeiyanYunyi commentedon Sep 14, 2021
依赖项上,需要安装
sass
来正确显示样式,当然也可以在代码里加载 jsdelivr 上的 css 。这是我的代码,其中
vd
会被设置为 Vditor 的实例以进行其他操作,如果不在其它地方使用的话,也可以不useState()
。btw,react-vditor 的
Readme
里也有用 hook 的示例代码。ghost commentedon Sep 14, 2021
BeiyanYunyi commentedon Sep 14, 2021
你的代码里,直接在组件函数内把 vditor 实例化是错误的。react 里,若组件状态有更新,则整个组件会被刷新,这样你那个实例化的过程就会被执行多次,带来性能上的损失,以及可能存在的 bug,比如你的代码实际上在自己的 DOM (return 的内容)被渲染出来之前就开始将 vditor 实例化了,这时 vditor 找不到那个 DOM。
正确的方法是像我的代码那样使用 useEffect,这个 hook 在其第二个参数(任意数组)的内容发生变动时才会运行其第一个参数(回调函数)。如果数组为空(如我的代码),则回调会在组件每次加载完成后被调用一次。按 react-vditor 的方法,性能会比我的更好一些(只要 vditor 实例不发生变动,就不再调用那段函数,相当于只在组件第一次加载时运行回调)
BeiyanYunyi commentedon Sep 14, 2021
另外我也建议作者更新一下 React 的示例代码。现在 React 流行
hook 增强的函数式组件
,原来的类组件已经不那么常见了。我学 React 用的教程里,类组件被放在比较靠后的位置,成为了某种“高阶技巧 / 拓展阅读”。React 官方 是这么写的:
We recommend trying Hooks in new code.
ghost commentedon Sep 14, 2021
BeiyanYunyi commentedon Sep 14, 2021
setValue 是 vditor 的内置方法。我代码里没有出现这个。我给改一下。
BeiyanYunyi commentedon Sep 14, 2021
改好了,应该改得比较清楚了。
ghost commentedon Sep 14, 2021
ghost commentedon Sep 14, 2021
感谢你的回答,辛苦辛苦
HengCC commentedon Feb 25, 2022
遇到了个比较奇怪的问题. 初始化过程和你一样. 初始化的时候加了定制的toolbar. 如下
以上click被执行的时候会调用
但是这个位置打印出来的editor是空的.. editor声明如下:
const [editor, setEditor] = useState<Vditor>();
after后set值的
诡异的是下面这样的effect中. 是能够获取到editor的值, 但是上面的取消触发后就无法获取
1zumii commentedon Mar 6, 2022
@lixiang810 我发现不用去
src/
目录下引用 scss,我在dist/
目录下找到了打包好的index.css
。引入后也正常显示了。这样就省去了还需要使用 scss 的步骤。HengCC commentedon Mar 7, 2022
我说的这个问题我找到问题点了. 主要是effect机制以及在其中初始化的问题. 需要监听editor的变更. 不然第一次after后执行获取的editor永远为空.
BeiyanYunyi commentedon Mar 7, 2022
@HengCC 和 Effect 确实有关,但是我觉得核心在于,setState 这个函数本质是异步的,你 setState 完了并不能直接用。
HengCC commentedon Mar 8, 2022
本质上是effect的机制决定的. 副作用如果不指定依赖的话,那么在当时的执行环境中如果editor没被初始化. 那就是获取不到值. 即使是依赖了也得这么写才能有值.