Черновик. js с Formik editorState.getCurrentContent не является функцией - PullRequest
0 голосов
/ 19 марта 2020

Я нашел этот черновик js с примером Formik на Codesandbox , и я пытаюсь реализовать его в своем проекте Next JS.

Я не понимаю, в чем здесь проблема.

Это мой код:

Артикул. js

import { useState, useEffect } from 'react';
import {  addArticle } from '../../store/actions/articleActions';
import { useDispatch, useSelector } from 'react-redux'
import * as Yup from 'yup'
import { Formik } from 'formik'
import dynamic from 'next/dynamic'

import {Editor, EditorState, convertToRaw, convertFromRaw } from 'draft-js';
import {stateToHTML} from 'draft-js-export-html';

import ArticleForm from './ArticleForm'

// reactstrap components
import {
    Card,
    CardBody,
    Container,
    Row,
    Col
  } from "reactstrap";

  const Article = () => {
      const initialArticle = {
          title: '',
          slug: '',
          content: EditorState.createEmpty()
      }

      const validationSchema = Yup.object({
        title: Yup.string()
        .min(3, "Password must be more than 3 charachters!")
        .max(20, "Password cant have more than 20 charachters"),
        content: Yup.string()
          .min(3, "Password must be more than 3 charachters!")
          .max(20, "Password cant have more than 20 charachters")

      })

      const dispatch = useDispatch()

      const handleSubmit = async (values) => {

        const html = stateToHTML(values.content.getCurrentContent()); 
        console.log("HTMLL", html)   
         const saveArticle = {
          title: values.title,
          slug: values.slug,
          content: html
        }
        console.log("articleee", saveArticle)
        dispatch(addArticle(saveArticle))
        console.log("articleee", saveArticle)
      }
      return (

        <main>
          <section className="">
            <Container className="pt-lg-md">
              <Row className="justify-content-center">
                <Col lg="12">
                  <Card className="bg-secondary shadow border-0">
                    <CardBody className="px-lg-5 py-lg-5">

                      <Formik
                enableReinitialize={true}
                component={ArticleForm}
                initialValues={initialArticle}
                validationSchema={validationSchema}
                validateOnChange={false}
                validateOnBlur={true}
                onSubmit={(values) => {
                  handleSubmit(values)
                }}
              />
                    </CardBody>
                  </Card>
                </Col>
              </Row>
            </Container>
          </section>
        </main>
    );


  };

  export default Article;

ArticleForm. js

import { Form } from 'formik'
import dynamic from 'next/dynamic'
import {Editor} from 'draft-js';

import { RichEditorExample } from '../../helpers/RichEditor';

// reactstrap components
import {
  Button,
  FormGroup,
  Input,
  InputGroupAddon,
  InputGroupText,
  InputGroup,
} from "reactstrap";


const ArticleForm = props => {

    const {
        values: {
          title,
          slug,
          content
        },
        handleChange,
        handleSubmit,
        setFieldValue,
        handleBlur
      } = props


        // Custom overrides for "code" style.


      return (
        <React.Fragment>

        <Form onSubmit={(e) => {
           e.preventDefault()
           console.log('submitted')
           handleSubmit()
          }}
          >
        <FormGroup>
            <InputGroup className="input-group-alternative mb-3">
              <InputGroupAddon addonType="prepend">
                <InputGroupText>
                  <i className="ni ni-lock-circle-open" />
                </InputGroupText>
              </InputGroupAddon>
              <Input
                placeholder="Title"
                type='text'
                name='title'
                value={title}
                onBlur={handleBlur}
                onChange={handleChange}
                />
            </InputGroup>
          </FormGroup>
          <FormGroup>
            <InputGroup className="input-group-alternative mb-3">
              <InputGroupAddon addonType="prepend">
                <InputGroupText>
                  <i className="ni ni-lock-circle-open" />
                </InputGroupText>
              </InputGroupAddon>
              <Input
                placeholder="Slug"
                type='text'
                name='slug'
                value={slug}
                onBlur={handleBlur}
                onChange={handleChange}
                />
            </InputGroup>
          </FormGroup>
          <FormGroup>


              <RichEditorExample
               editorState={content}
               onChange={value => setFieldValue("content", value)}

              />

          </FormGroup>






          <div className="text-center">
            <Button
              className="mt-4"
              color="primary"
              type="submit"
            >
              Create
            </Button>
          </div>
        </Form>
        </React.Fragment>

);


}

export default ArticleForm;

RichEditorExample. js

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

export class RichEditorExample extends React.Component {
  onChange = editorState => {
    const raw = convertToRaw(editorState.getCurrentContent());
    const inputValue = convertFromRaw(raw);
    console.log("@@raw", { raw, inputValue });

    this.props.onChange("editorState", editorState);
  };

  focus = () => this.refs.editor.focus();

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

  onTab = e => {
    const maxDepth = 4;
    this.onChange(RichUtils.onTab(e, this.props.editorState, maxDepth));
  };
  toggleBlockType = blockType => {
    this.onChange(RichUtils.toggleBlockType(this.props.editorState, blockType));
  };
  toggleInlineStyle = inlineStyle => {
    this.onChange(
      RichUtils.toggleInlineStyle(this.props.editorState, inlineStyle)
    );
  };
  render() {
    const { editorState } = this.props;

    // 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() ;

    console.log("contentState", contentState)
    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}
            onTab={this.onTab}
            placeholder=""
            ref="editor"
            spellCheck={true}
          />
        </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>
  );
};

Ранее я пытался реализовать редактор реакции-перо аналогичным образом, но есть проблема, которую я могу ' t жирный текст, и я не могу сохранить в базе данных более 2 слов. Поэтому я решил попробовать с Draft JS.

Если вы можете мне помочь, я буду очень благодарен!

...