[英]How to access ReactQuill Ref when using dynamic import in NextJS?
我遇到了一个有趣的问题。 我将 NextJS 用于其服务器端渲染功能,并使用 ReactQuill 作为我的富文本编辑器。 为了绕过 ReactQuill 与 DOM 的联系,我动态地导入了它。 但是,这带来了另一个问题,即当我尝试将 ref 附加到 ReactQuill 组件时,它被视为可加载组件而不是 ReactQuill 组件。 我需要 ref 来自定义上传到富文本编辑器时如何处理图像。 现在,ref 返回 current:null 而不是我可以使用 .getEditor() on 自定义图像处理的函数。
有人对我如何解决这个问题有任何想法吗? 我尝试了引用转发,但它仍然将引用应用于可加载组件,而不是 React-Quill 组件。 这是我的代码的快照。
const ReactQuill = dynamic(import('react-quill'), { ssr: false, loading: () => <p>Loading ...</p> }
);
const ForwardedRefComponent = React.forwardRef((props, ref) => {return (
<ReactQuill {...props} forwardedRef={(el) => {ref = el;}} />
)})
class Create extends Component {
constructor() {
super();
this.reactQuillRef = React.createRef();
}
imageHandler = () => {
console.log(this.reactQuillRef); //this returns current:null, can't use getEditor() on it.
}
render() {
const modules = {
toolbar: {
container: [[{ 'header': [ 2, 3, false] }],
['bold', 'italic', 'underline', 'strike'],
[{ 'list': 'ordered'}, { 'list': 'bullet' }],
[{ 'script': 'sub'}, { 'script': 'super' }],
['link', 'image'],
[{ 'indent': '-1'}, { 'indent': '+1' }],
[{ 'align': [] }],
['blockquote', 'code-block'],],
handlers: {
'image': this.imageHandler
}
}
};
return(
<ForwardedRefComponent
value={this.state.text}
onChange={this.handleChange}
modules={modules}
ref={this.reactQuillRef}/> //this.reactQuillRef is returning current:null instead of the ReactQuill function for me to use .getEditor() on
)
}
}
const mapStateToProps = state => ({
tutorial: state.tutorial,
});
export default connect(
mapStateToProps, {createTutorial}
)(Create);
在 NextJS 中,React.useRef 或 React.createRef 不适用于动态导入。
你应该更换
const ReactQuill = dynamic(import('react-quill'), { ssr: false, loading: () => <p>Loading ...</p> }
);
和
import ReactQuill from 'react-quill';
并在加载window
后渲染。
import ReactQuill from 'react-quill';
class Create extends Component {
constructor() {
super();
this.reactQuillRef = React.createRef();
this.state = {isWindowLoaded: false};
}
componentDidMount() {
this.setState({...this.state, isWindowLoaded: true});
}
.........
.........
render(){
return (
<div>
{this.isWindowLoaded && <ReactQuil {...this.props}/>}
</div>
)
}
}
使用 onChange 并传递所有参数,这里有一个使用 editor.getHTML() 的示例
import React, { Component } from 'react'
import dynamic from 'next/dynamic'
import { render } from 'react-dom'
const QuillNoSSRWrapper = dynamic(import('react-quill'), {
ssr: false,
loading: () => <p>Loading ...</p>,
})
const modules = {
toolbar: [
[{ header: '1' }, { header: '2' }, { font: [] }],
[{ size: [] }],
['bold', 'italic', 'underline', 'strike', 'blockquote'],
[
{ list: 'ordered' },
{ list: 'bullet' },
{ indent: '-1' },
{ indent: '+1' },
],
['link', 'image', 'video'],
['clean'],
],
clipboard: {
// toggle to add extra line breaks when pasting HTML:
matchVisual: false,
},
}
/*
* Quill editor formats
* See https://quilljs.com/docs/formats/
*/
const formats = [
'header',
'font',
'size',
'bold',
'italic',
'underline',
'strike',
'blockquote',
'list',
'bullet',
'indent',
'link',
'image',
'video',
]
class BlogEditor extends Component {
constructor(props) {
super(props)
this.state = { value: null } // You can also pass a Quill Delta here
this.handleChange = this.handleChange.bind(this)
this.editor = React.createRef()
}
handleChange = (content, delta, source, editor) => {
this.setState({ value: editor.getHTML() })
}
render() {
return (
<>
<div dangerouslySetInnerHTML={{ __html: this.state.value }} />
<QuillNoSSRWrapper ref={this.editor} onChange={this.handleChange} modules={modules} formats={formats} theme="snow" />
<QuillNoSSRWrapper value={this.state.value} modules={modules} formats={formats} theme="snow" />
</>
)
}
}
export default BlogEditor
我分享我的解决方案,希望它对你也有帮助。
来自https://github.com/zenomaro/react-quill/issues/642#issuecomment-717661518的帮助
const ReactQuill = dynamic( async () => { const { default: RQ } = await import("react-quill"); return ({ forwardedRef, ...props }) => <RQ ref={forwardedRef} {...props} />; }, { ssr: false } ); export default function QuillWrapper() { const quillRef = React.useRef(false) return <> <ReactQuill forwardedRef={quillRef} /> </> }
例如,您可以使用 ref 使用自定义处理程序上传图像
const ReactQuill = dynamic( async () => { const { default: RQ } = await import("react-quill"); return ({ forwardedRef, ...props }) => <RQ ref={forwardedRef} {...props} />; }, { ssr: false } ); export default function QuillWrapper({ value, onChange, ...props }) { const quillRef = React.useRef(false) // Custom image upload handler function imgHandler() { // from https://github.com/quilljs/quill/issues/1089#issuecomment-318066471 const quill = quillRef.current.getEditor() let fileInput = quill.root.querySelector('input.ql-image[type=file]'); // to prevent duplicate initialization I guess if (fileInput === null) { fileInput = document.createElement('input'); fileInput.setAttribute('type', 'file'); fileInput.setAttribute('accept', 'image/png, image/gif, image/jpeg, image/bmp, image/x-icon'); fileInput.classList.add('ql-image'); fileInput.addEventListener('change', () => { const files = fileInput.files; const range = quill.getSelection(true); if (!files || !files.length) { console.log('No files selected'); return; } const formData = new FormData(); formData.append('file', files[0]); formData.append('uid', uid) formData.append('img_type', 'detail') quill.enable(false); axios .post('the/url/for/handle/uploading', formData) .then(response => { // after uploading succeed add img tag in the editor. // for detail visit https://quilljs.com/docs/api/#editor quill.enable(true); quill.insertEmbed(range.index, 'image', response.data.url); quill.setSelection(range.index + 1); fileInput.value = ''; }) .catch(error => { console.log('quill image upload failed'); console.log(error); quill.enable(true); }); }); quill.root.appendChild(fileInput); } fileInput.click(); } // I don't know much about useMemo // but if i don't use the hook, // the editor keeps rerendered resulting in losing focus and I guess perfomance trouble too. const modules = useMemo(() => ({ toolbar: { container: [ [{ font: [] }], [{ size: ["small", false, "large", "huge"] }], // custom dropdown ["bold", "italic", "underline", "strike"], // toggled buttons [{ color: [] }, { background: [] }], // dropdown with defaults from theme [{ script: "sub" }, { script: "super" }], // superscript/subscript [{ header: 1 }, { header: 2 }], // custom button values ["blockquote", "code-block"], [{ list: "ordered" }, { list: "bullet" }], [{ indent: "-1" }, { indent: "+1" }], // outdent/indent [{ direction: "rtl" }], // text direction [{ align: [] }], ["link", "image"], ["clean"], // remove formatting button ], handlers: { image: imgHandler } // Custom image handler } }), []) return <ReactQuill forwardedRef={quillRef} modules={modules} value={value} onChange={onChange} {...props}/> }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.