2

当实现为 Contentful SDK 的字段修改时,我正在尝试更改 react-quill 的撤消/重做行为。该实现由https://github.com/contentful/create-contentful-app/tree/master/template上的模板描述。

天真的实现时,Ctrl-Z 键盘快捷键会完全清除 react-quill 编辑器。在历史模块中实现userOnly: true解决了这个问题,但我想使用工具栏中的按钮通过直接访问 react-quill 的增量和历史功能来控制撤消/重做行为。

我已修改https://github.com/contentful/create-contentful-app/blob/master/template/src/components/Field.tsx如下:

import React, {useState, useEffect, useRef, createRef} from 'react';
import { Paragraph } from '@contentful/forma-36-react-components';
import { FieldExtensionSDK } from 'contentful-ui-extensions-sdk';
import ReactQuill from 'react-quill';
import 'react-quill/dist/quill.snow.css';

const formats = ['header','bold', 'italic', 'underline', 'strike', 'blockquote','list', 'bullet', 'indent','link', 'image', 'undo', 'redo'];

let icons = ReactQuill.Quill.import("ui/icons");

interface FieldProps { sdk: FieldExtensionSDK; }

let mainRef = React.createRef<ReactQuill>();

const Field = (props: FieldProps) => {
  const [value, setValue] = useState('');

  useEffect (()=> {
    // CMS update code here - removed for clarity
  }, [])

  const modules = {
    toolbar: {
      container: [
        [
          { 'header': [1, 2, false] }
        ],
        ['bold', 'italic'],
        [
          {'list': 'ordered'},
          {'list': 'bullet'}
        ],
        ['link'],
        ['image'],
        ['undo'],
        ['redo']
      ],
      handlers: {
        'undo': function () {
          console.log(mainRef.current)
        },
        'redo': function () {
          console.log(mainRef.current)
        }
      }
    },
    history: {
      delay: 200,
      maxStack: 500,
      userOnly: true
    }
  };

  return <div>
        <ReactQuill id='quillmain' modules={modules} formats={formats} theme="snow" value={value} onChange={setValue} ref={mainRef}/>
    </div>
  ;
};

export default Field;

上面定义的撤消和重做处理程序将成功触发 - 在单击撤消或重做图标时,我将根据我创建的参考获得 ReactQuill 实例当前状态的控制台输出:

控制台输出

我想访问定义在https://quilljs.com/docs/modules/history/的历史模块控件,这样我就可以有效地调用 mainRef.current.history.undo() 和 redo() 之类的东西。但是如果我尝试在我的模块 const 声明中调用它们,我会遇到 ReactQuill 实例的状态问题:

console.log(mainRef.current.history)
>>
Object is possibly 'null'.  TS2531

试图强迫这个问题没有帮助:

console.log(mainRef.current!.history)
>>
Property 'history' does not exist on type 'ReactQuill'.  TS2339

但是根据上面的屏幕截图,打印当前实例表明历史属性可用,我假设不是在声明模块 const 的时候。将声明移到模块 const 之外没有帮助 - 遇到相同的 TS 错误。

根据这个答案,这感觉应该是可能的:如何在 Quill JS (react-quill) 中创建撤消/重做按钮?,但我觉得好像受限于功能组件、打字稿和钩子的组合,都在密谋阻止我以我需要的方式使用 react-quill。

谁能建议我如何访问 ReactQuill 实例,以便我可以根据需要调用 undo() 和 redo() 函数,或者,如何在这些限制下实现 react-quill 以便撤消功能按预期工作?

4

2 回答 2

1

这里的答案是useCallback。正如怀疑的那样,内联函数导致组件出现状态问题,但 useCallback 允许声明内联函数,同时保持所需的 react-quill 行为。以下代码允许受控内联函数触发,同时保持所需的撤消/重做行为:

const modules = {
  toolbar: {
    container: [
      [
        { 'header': [1, 2, false] }
      ],
      ['bold', 'italic'],
      [
        {'list': 'ordered'},
        {'list': 'bullet'}
      ],
      ['link'],
      ['image'],
      ['undo'],
      ['redo']
    ],
    handlers: {
      'undo': React.useCallback(undoFunc => {
        console.log(mainRef.current) // DOES NOT BREAK QUILL STATE!
      }, [])
      'redo': function () {
        console.log(mainRef.current) // BREAKS QUILL STATE!
      }
    }
  },
  history: {
    delay: 200,
    maxStack: 500,
    userOnly: true
  }
};

使用 useCallback 而不是内联函数声明模块 const 可以实现所需的行为。

于 2020-11-18T15:54:34.813 回答
0
import ReactQuill, { Quill } from 'react-quill';

let mainRef = React.createRef<ReactQuill>();
.....
....
..
.
const modules = {
  toolbar: {
    container: [
      [
        { 'header': [1, 2, false] }
      ],
      ['bold', 'italic'],
      [
        {'list': 'ordered'},
        {'list': 'bullet'}
      ],
      ['link'],
      ['image'],
      ['undo'],
      ['redo']
    ],
    handlers: {
      'undo': () => {
        let myEditor: any = mainRef?.current?.getEditor();
        return myEditor?.history?.undo();
      },
      'redo': function () {
        let myEditor: any = mainRef?.current?.getEditor();
        return myEditor?.history?.redo();
      }
    }
  },
  history: {
    delay: 200,
    maxStack: 500,
    userOnly: true
  }
};

return (
    <ReactQuill
      theme="snow"
      value={props.value}
      onChange={props.onChange}
      placeholder={'Write something awesome...'}
      modules={modules}
      ref={mainRef}
      formats={formats}
    />
  );

尝试这样做,它对我有用!

于 2021-09-09T10:03:12.747 回答