繁体   English   中英

在单个页面中将高阶组件与多个Draft.js编辑器一起使用

[英]Using a higher order component with multiple Draft.js editors in single page

我正在制作一个由八个不同组件组成的主页,这些组件代表页面内容的各个方面。 我希望使用使用Draft.js的自定义内置InlineEditor组件可编辑其中三个。 当我最初尝试执行此操作时,第二个和第三个组件的编辑工具栏将仅在第一个组件上起作用。 因此,这是Draft.js问题。 通过创建三个单独的InlineEditor组件,然后在必要时分别使用每个组件,我能够使所有工作正常进行,但这似乎是多余的。

我认为必须有一种更好的方法来使用HOC或render props但是我正在努力正确地进行设置。 有什么想法可能是更好的解决方案?

这是初始的InlineEditor组件:

import React, { Component } from 'react'
import { connect } from 'react-redux'
import { EditorState, convertFromRaw } from 'draft-js'
import Editor from 'draft-js-plugins-editor'
import createUndoPlugin from 'draft-js-undo-plugin'
import createToolbarPlugin, { Separator } from 'draft-js-static-toolbar-plugin'
import createToolbarLinkPlugin from 'draft-js-toolbar-link-plugin'
import {
  ItalicButton,
  BoldButton,
  UnderlineButton,
  CodeButton,
  HeadlineOneButton,
  HeadlineTwoButton,
  HeadlineThreeButton,
  UnorderedListButton,
  OrderedListButton,
  BlockquoteButton,
  CodeBlockButton
} from 'draft-js-buttons'
import { Flex, Box } from 'rebass'
import FontAwesome from 'react-fontawesome'
import {
  ToolbarNav,
  EditPanel,
  StaticToolbar,
  TextInfo,
  DefaultButton,
  SuccessButton,
  InlineLink
} from 'styles'

// Set up Draft.js toolbar and plugins
const undoPlugin = createUndoPlugin()
const toolbarLinkPlugin = createToolbarLinkPlugin({
  inputPlaceholder: 'Insert URL here...'
})
const { LinkButton } = toolbarLinkPlugin
const { UndoButton, RedoButton } = undoPlugin
const toolbarPlugin = createToolbarPlugin({
  structure: [
    BoldButton,
    ItalicButton,
    UnderlineButton,
    CodeButton,
    Separator,
    HeadlineOneButton,
    HeadlineTwoButton,
    HeadlineThreeButton,
    Separator,
    UnorderedListButton,
    OrderedListButton,
    BlockquoteButton,
    CodeBlockButton,
    LinkButton,
    Separator,
    UndoButton,
    RedoButton
  ]
})
const { Toolbar } = toolbarPlugin
const plugins = [toolbarPlugin, toolbarLinkPlugin, undoPlugin]

class InlineEditor extends Component {
  displayName = 'inline editor component'
  constructor(props) {
    super(props)

    this.state = {
      editorState: EditorState.createWithContent(
        convertFromRaw(this.props.rawContent)
      ),
      showURLInput: false,
      urlValue: '',
      readOnly: true
    }
  }
  onChange = editorState => this.setState({ editorState })
  focus = () => this.refs.editor.focus()
  onEdit = e => {
    e.preventDefault()
    this.setState({
      readOnly: false
    })
  }
  onSave = () => {
    // save new content
    this.setState({
      showURLInput: false,
      urlValue: '',
      readOnly: true
    })
  }
  onCancel = () => {
    // cancel editing
    this.setState({
      editorState: EditorState.createWithContent(
        convertFromRaw(this.props.rawContent),
        this.decorator
      ),
      showURLInput: false,
      urlValue: '',
      readOnly: true
    })
  }
  renderToolbar = () => {
    return (
      <ToolbarNav>
        <StaticToolbar>
          <Toolbar />
        </StaticToolbar>
      </ToolbarNav>
    )
  }
  render() {
    const { editorState, readOnly } = this.state
    const { auth } = this.props
    return (
      <EditPanel>
        <Flex wrap>
          <Box w={'90%'}>{!readOnly && this.renderToolbar()}</Box>
          <Box mt={1}>
            <Editor
              editorState={editorState}
              onChange={this.onChange}
              plugins={plugins}
              ref="{(element) => { this.editor = element }}"
              readOnly={readOnly}
            />
            {auth.isAuthenticated &&
              readOnly && (
                <TextInfo>
                  <InlineLink onClick={this.onEdit} title="Edit">
                    <FontAwesome name="pencil" /> Edit
                  </InlineLink>
                </TextInfo>
              )}
          </Box>
          <Box width={'40%'} mr={1} mt={1}>
            {!readOnly && (
              <DefaultButton
                className={`block`}
                type="button"
                onClick={this.onCancel}>
                Cancel
              </DefaultButton>
            )}
          </Box>
          <Box width={'40%'} mt={1}>
            {!readOnly && (
              <SuccessButton
                className={`block`}
                type="button"
                onClick={this.onSave}>
                Save
              </SuccessButton>
            )}
          </Box>
        </Flex>
      </EditPanel>
    )
  }
}

const mapStateToProps = state => {
  return {
    auth: state.auth
  }
}

export default connect(mapStateToProps)(InlineEditor)

当前,诸如About类的组件正在访问它,如下所示:

return (
    <InlineEditor
    auth={ this.props.auth }
    rawContent={ about }/>
)

我可以通过创建一个InlineEditor组件来解决此问题, InlineEditor组件在其constructor (即,

constructor(props) {
    super(props)

    this.undoPlugin = createUndoPlugin()

    this.toolbarLinkPlugin = createToolbarLinkPlugin({
       inputPlaceholder: "Insert URL here...",
    })

    // etc...
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM