如何在编辑器中显示保存的Draft-JS数据?(React + Meteor)

4

我正在尝试在编辑器中保存已保存的内容(例如刷新后)。

  • 目前,内容从数据库传输到console.log,并按预期显示。
  • 但是我无法将其保留在编辑器中。

[编辑] 删除了草稿项目链接,请参见下面的解决方案。

我正在使用:
Draft-JS
react-draft-wysiwyg

这是~/imports/collections/bins.js

    import { Mongo } from 'meteor/mongo';

    Meteor.methods({
      'bins.insert': function() {
        return Bins.insert({
          createdAt: new Date(),
          content: '',
          sharedWith: [],
          ownerId: this.userId
        });
      },

      'bins.remove': function(bin) {
        return Bins.remove(bin);
      },

      'bins.update': function(bin, content) {
        return Bins.update(bin._id, { $set: { content } });
      }
    });

    export const Bins = new Mongo.Collection('bins');

~/client/components/bins/bins_main.js

    import React, { Component } from 'react';
    import { createContainer } from 'meteor/react-meteor-data';
    import { Bins } from '../../../imports/collections/bins';
    import BinsEditor from './bins_editor';

    class BinsMain extends Component {
      render() {
        if (!this.props.bin) { return <div>Loading...</div>; }

        return (
          <div>
            <BinsEditor bin={this.props.bin} />
          </div>
        );
      }
    }

    export default createContainer((props) => {
      const { binId } = props.params;
      Meteor.subscribe('bins');

      return { bin: Bins.findOne(binId) };
    }, BinsMain);

请问您能提供更多信息吗?听起来像是数据订阅的问题,React 代码只是渲染部分。 - Mikkel
我还没有尝试过你的代码,但是这里有两个问题可能会有所帮助。为什么在handleChange方法中没有使用this.setState({editorState})来更新状态?Editor组件上的defaultEditorState属性是什么意思?也许editorState属性才是你要找的?希望能有所帮助。 - Laurent Van Winckel
@LaurentVanWinckel 哈哈,你是我的童年朋友Laurent Van Winckel吗?我是Sebastien。 - user6198643
谢谢你的帮助,我认为你是对的,但我仍然无法在编辑器中检索数据。如果问题确实存在,我想当我输入时我的文本甚至不会出现在编辑器中。在 if (props.content) { const rawContent = this.props.bin.content; const contentState = convertFromRaw(JSON.parse(rawContent)); editorState = EditorState.createWithContent(blocks); } 这部分中一定有些问题,我猜测它没有按预期检索到数据。 - user6198643
@LaurentVanWinckel 哈哈,这是什么概率!但是使用props.bin.content我失去了.. 啊啊 - user6198643
显示剩余2条评论
1个回答

1

这里是 示例应用程序 - 它是使用 Draft-JS + React + Meteor + Material-UI + Accounts-UI + Material-UI-Accounts 的完整示例。

您可以:

  • 创建与您的用户帐户链接的 bin(如果已登录)
  • 编辑 bin
  • 在编辑时自动保存 bin

这里是 bins_editor.js

    import React from "react";
    import {Editor, EditorState, ContentState, RichUtils, convertToRaw, convertFromRaw} from "draft-js";

    export default class BinsEditor extends React.Component {

      constructor(props) {
        super(props);

        let editorState;


        if (!this.props.bin.content) {
            this.state = {editorState: EditorState.createEmpty()};
            console.log('empty');
          } else {
            const rawContent = this.props.bin.content;
            const parsedContent = convertFromRaw(JSON.parse(rawContent));

            this.state = {editorState: EditorState.createWithContent(parsedContent)};
            console.log('not empty');
          }
            this.focus = () => this.refs.editor.focus();
            this.onChange = (editorState) => {
              this.setState({editorState});
              const contentState = editorState.getCurrentContent();
              const rawContent = JSON.stringify(convertToRaw(contentState));

              Meteor.call('bins.update', this.props.bin, rawContent);
              console.log(rawContent);
            }

            this.handleKeyCommand = (command) => this._handleKeyCommand(command);
            this.toggleBlockType = (type) => this._toggleBlockType(type);
            this.toggleInlineStyle = (style) => this._toggleInlineStyle(style);
      }

      _handleKeyCommand(command) {
        const {editorState} = this.state;
        const newState = RichUtils.handleKeyCommand(editorState, command);
        if (newState) {
          this.onChange(newState);
          return true;
        }
        return false;
      }

      _toggleBlockType(blockType) {
        this.onChange(
          RichUtils.toggleBlockType(
            this.state.editorState,
            blockType
          )
        );
      }

      _toggleInlineStyle(inlineStyle) {
        this.onChange(
          RichUtils.toggleInlineStyle(
            this.state.editorState,
            inlineStyle
          )
        );
      }

      render() {
        const {editorState} = this.state;

        // If the user changes block type before entering any text, we can
        // either style the placeholder or hide it. Let's just hide it now.
        let className = 'RichEditor-editor';
        var contentState = editorState.getCurrentContent();
        if (!contentState.hasText()) {
          if (contentState.getBlockMap().first().getType() !== 'unstyled') {
            className += ' RichEditor-hidePlaceholder';
          }
        }

        return (
          <div className="RichEditor-root">
            <BlockStyleControls
              editorState={editorState}
              onToggle={this.toggleBlockType}
            />
            <InlineStyleControls
              editorState={editorState}
              onToggle={this.toggleInlineStyle}
            />
            <div className={className} onClick={this.focus}>
              <Editor
                blockStyleFn={getBlockStyle}
                customStyleMap={styleMap}
                editorState={editorState}
                handleKeyCommand={this.handleKeyCommand}
                onChange={this.onChange}
                placeholder="Tell a story..."
                ref="editor"
                spellCheck={true}
              />
            </div>
            <div>{JSON.stringify(convertToRaw(editorState.getCurrentContent()))}</div>
          </div>
        );
      }
    }

    // Custom overrides for "code" style.
    const styleMap = {
      CODE: {
        backgroundColor: 'rgba(0, 0, 0, 0.05)',
        fontFamily: '"Inconsolata", "Menlo", "Consolas", monospace',
        fontSize: 16,
        padding: 2,
      },
    };

    function getBlockStyle(block) {
      switch (block.getType()) {
        case 'blockquote': return 'RichEditor-blockquote';
        default: return null;
      }
    }

    class StyleButton extends React.Component {
      constructor() {
        super();
        this.onToggle = (e) => {
          e.preventDefault();
          this.props.onToggle(this.props.style);
        };
      }

      render() {
        let className = 'RichEditor-styleButton';
        if (this.props.active) {
          className += ' RichEditor-activeButton';
        }

        return (
          <span className={className} onMouseDown={this.onToggle}>
            {this.props.label}
          </span>
        );
      }
    }

    const BLOCK_TYPES = [
      {label: 'H1', style: 'header-one'},
      {label: 'H2', style: 'header-two'},
      {label: 'H3', style: 'header-three'},
      {label: 'H4', style: 'header-four'},
      {label: 'H5', style: 'header-five'},
      {label: 'H6', style: 'header-six'},
      {label: 'Blockquote', style: 'blockquote'},
      {label: 'UL', style: 'unordered-list-item'},
      {label: 'OL', style: 'ordered-list-item'},
      {label: 'Code Block', style: 'code-block'},
    ];

    const BlockStyleControls = (props) => {
      const {editorState} = props;
      const selection = editorState.getSelection();
      const blockType = editorState
        .getCurrentContent()
        .getBlockForKey(selection.getStartKey())
        .getType();

      return (
        <div className="RichEditor-controls">
          {BLOCK_TYPES.map((type) =>
            <StyleButton
              key={type.label}
              active={type.style === blockType}
              label={type.label}
              onToggle={props.onToggle}
              style={type.style}
            />
          )}
        </div>
      );
    };

    var INLINE_STYLES = [
      {label: 'Bold', style: 'BOLD'},
      {label: 'Italic', style: 'ITALIC'},
      {label: 'Underline', style: 'UNDERLINE'},
      {label: 'Monospace', style: 'CODE'},
    ];

    const InlineStyleControls = (props) => {
      var currentStyle = props.editorState.getCurrentInlineStyle();
      return (
        <div className="RichEditor-controls">
          {INLINE_STYLES.map(type =>
            <StyleButton
              key={type.label}
              active={currentStyle.has(type.style)}
              label={type.label}
              onToggle={props.onToggle}
              style={type.style}
            />
          )}
        </div>
      );
    };

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接