I'm trying to initialise TinyMCE, and have written it as a React Component. Using the code below, the editor renders, but after 10 seconds displays the following error:
tinymce can only be initialised when in a document
at Editor._this.initialise (http://localhost:4052/bundle.js:89548:27)
at http://localhost:4052/bundle.js:89544:59
Using the npm package `@tinymce/tinymce-react', and following the setup guide, I've produced the following component:
import React, { useEffect, useRef, useState } from 'react'
import { Editor } from '@tinymce/tinymce-react'
import { Box, Button } from '@mui/material'
const TinyMCE = ({ initialValue, onSubmit }) => {
const [loaded, setLoaded] = useState(false)
const [value, setValue] = useState(initialValue ?? '<p></p>')
useEffect(() => {
setLoaded(true)
}, [])
const editorRef = useRef(null)
const handleChange = (e) => setValue(e.content)
const handleSubmit = () => console.log(value)
return (
<Box>
<Box id="tinymceeditor" />
<Editor
value={value}
onEditorChange={handleChange}
apiKey="*****"
init={{
selector: 'tinymceeditor',
plugins: 'advlist code emoticons link lists table',
toolbar: 'bold italic | bullist numlist | link emoticons',
height: 300
}}
/>
<Button variant="contained" color="primary" onClick={handleSubmit}>
Submit
</Button>
</Box>
)
}
export default TinyMCE
The npm package throws the error after 10 seconds, from here:
_this.initialise = function (attempts) {
var _a, _b, _c;
if (attempts === void 0) { attempts = 0; }
var target = _this.elementRef.current;
if (!target) {
return; // Editor has been unmounted
}
if (!(0, Utils_1.isInDoc)(target)) {
// this is probably someone trying to help by rendering us offscreen
// but we can't do that because the editor iframe must be in the document
// in order to have state
if (attempts === 0) {
// we probably just need to wait for the current events to be processed
setTimeout(function () { return _this.initialise(1); }, 1);
}
else if (attempts < 100) {
// wait for ten seconds, polling every tenth of a second
setTimeout(function () { return _this.initialise(attempts + 1); }, 100);
}
else {
// give up, at this point it seems that more polling is unlikely to help
throw new Error('tinymce can only be initialised when in a document');
}
return;
}
Whilst I cannot find any examples of the exact same error, I assume it's something to do with the initialisation. I've tried rendering the component only after the parent component mounted.
The Editor component accepts an oninit parameter. I've tried using this to update the ref onInit={(evt, editor) => (editorRef.current = editor)} but this does not affect the error being thrown.
One forum suggested it was webpack, so I included the MiniCssExtractPlugin as per their suggestion there. Here is my webpack config:
module.exports = {
entry: {
app: './src/index.js'
},
module: {
rules: [
{
test: /\.(ts|js|jsx)x?$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader',
options: {
presets: ['@babel/env']
}
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(png|jpe?g|gif)$/i,
use: ['file-loader']
}
]
},
resolve: {
extensions: ['*', '.js', '.jsx']
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
clean: true
},
plugins: [
new Dotenv(),
new HtmlWebpackPlugin({
template: './src/assets/index.html',
favicon: './src/assets/images/icons/favicons/favicon.ico',
meta: {viewport: 'width=device-width, initial-scale=1'}
}),
new MiniCssExtractPlugin()
],
}
Any help would be really appreciated!
I think I've found your problem.
You have that Box element with
id=tinymceeditor, and in Editor'sinityou have aselector: "tinymceeditor". This may cause this bug, Editor may try to choose that element with selector value.Change
<Box id="tinymceeditor" />to<Box id="boxId" />and removeselector: 'tinymceeditor'in Editor's init.