【问题标题】:Contentful SDK, React functional components, typescript and react-quill - unable to access quill history?内容丰富的 SDK、React 功能组件、打字稿和 react-quill - 无法访问 quill 历史记录?
【发布时间】:2021-02-24 12:53:08
【问题描述】:

当实现为 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 实例当前状态的控制台输出:

console output

我想访问定义在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 错误。

按照这个答案,这感觉应该是可能的:How to create undo/redo buttons in Quill JS (react-quill)?,但我觉得好像仅限于功能组件、打字稿和钩子的组合都在密谋阻止我使用 react-quill以我需要的方式。

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

【问题讨论】:

  • 我在这方面取得了一些进展,但仍然没有解决。
  • 我可以通过键盘快捷键访问 Quill 中的撤消功能,但前提是我从模块 const 声明中删除了内联函数。我认为这是因为我正在更新内联函数中的状态,即调用 setValue 并导致钩子自行循环,但撤消行为发生在最简单的处理程序声明中:handlers: {'undo': function () {console.log("Undo") } } 如果我在模块 const 之外声明函数,撤消工作:'undo': undoFunc() 内联函数是原因

标签: typescript react-hooks contentful react-quill


【解决方案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 可以实现所需的行为。

【讨论】:

    【解决方案2】:
    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}
        />
      );
    

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

    【讨论】:

      猜你喜欢
      • 2020-02-25
      • 2019-08-03
      • 1970-01-01
      • 2019-01-06
      • 2023-03-30
      • 2020-05-19
      • 1970-01-01
      • 2019-05-09
      • 2019-03-19
      相关资源
      最近更新 更多