jpuri / react-draft-wysiwyg

A Wysiwyg editor build on top of ReactJS and DraftJS. https://jpuri.github.io/react-draft-wysiwyg
MIT License
6.42k stars 1.16k forks source link

Uncaught TypeError: editorState.getImmutable is not a function #204

Closed ryanaleksander closed 7 years ago

ryanaleksander commented 7 years ago

I've got this error whenever I issued any actions with the editor.

Uncaught TypeError: editorState.getImmutable is not a function
    at Function.set (EditorState.js:78)
    at e.value (react-draft-wysiwyg.js:38)
    at ReactCompositeComponent.js:611
    at measureLifeCyclePerf (ReactCompositeComponent.js:75)
    at ReactCompositeComponentWrapper.updateComponent (ReactCompositeComponent.js:610)
    at ReactCompositeComponentWrapper.receiveComponent (ReactCompositeComponent.js:547)
    at Object.receiveComponent (ReactReconciler.js:125)
    at Object.updateChildren (ReactChildReconciler.js:109)
    at ReactDOMComponent._reconcilerUpdateChildren (ReactMultiChild.js:208)
    at ReactDOMComponent._updateChildren (ReactMultiChild.js:312)

Code (unnecessary details omitted)

import {Editor} from "react-draft-wysiwyg";
import {EditorState} from "draft-js"

this.state = {
      detail: EditorState.createEmpty(),
};

onDetailChange(value) {
    this.setState({ detail: value });
    this.props.onChange({ ...this.state, detail: value });
 }

<Editor editorState={this.state.detail} onChange={this.onDetailChange.bind(this)} />
jpuri commented 7 years ago

Hey @ryanaleksander , what version of the lib and draftjs are you using ?

ryanaleksander commented 7 years ago

@jpuri I'm using draft.js 0.10.0 and react-draft-wysiwyg 1.7.0

EDIT: the editor is also rendered without a default border, if this information is of use.

jpuri commented 7 years ago

I do not expect this this kind of issue in latest version, let me again check and get back to you in some time.

jpuri commented 7 years ago

@ryanaleksander: I could not replicate the issue using code above. Can you share your whole component - that will help me see the issue.

ryanaleksander commented 7 years ago

The component

import React from "react";
import Select from "react-select";
import {Editor} from "react-draft-wysiwyg";
import {EditorState} from "draft-js";

export default class PostEditor extends React.Component {
  constructor(props) {
    super(props);

    this.renderEditor = this.renderEditor.bind(this);

    this.state = {
      title: "",
      detail: EditorState.createEmpty(),
      tags: [],
    };
  }

  onTitleChange(event) {
    this.setState({ title: event.target.value });
    this.props.onChange({ ...this.state, title: this.state.title });
  }

  onDetailChange(value) {
    this.setState({ detail: value });
    this.props.onChange({ ...this.state, detail: value });
  }

  onTagsChange(value) {
    this.setState({ tags: value });
    this.props.onChange({ ...this.state, tags: value });
  }

  renderEditor() {
    return (
      <div>
        <h3>Detail</h3>
        <Editor editorState={this.state.detail} onChange={this.onDetailChange.bind(this)}
                editorStyle={{border:"1px solid #f4f4f4", height:"300px"}}
        />
      </div>
    )
  }

  handleSubmit() {
    this.props.handleSubmit({ title: this.state.title, detail: this.state.detail });
  }

  render() {
    return (
      <div className="container-fluid editor">
        <h3>{this.props.title}</h3>
        <input className="form-control" placeholder={this.props.placeholder} value={this.state.title}
               onChange={this.onTitleChange.bind(this)} autoFocus="autoFocus"/>
        <br/>
        {this.props.detail ? this.renderEditor() : "" }
        <h4>Tags</h4>
        <Select className="form-control" options={this.props.tags} value={this.state.tags}
                onChange={this.onTagsChange.bind(this)} multi={true} />
      </div>
    )
  }
}

package.json

"dependencies": {
    "axios": "^0.15.3",
    "bootstrap": "^4.0.0-alpha.6",
    "draft-js": "^0.10.0",
    "jquery": "^3.1.1",
    "jquery-ui": "^1.12.1",
    "moment": "^2.17.1",
    "react": "^15.4.2",
    "react-dom": "^15.4.2",
    "react-draft-wysiwyg": "^1.7.0",
    "react-loading": "0.0.9",
    "react-quill": "^0.4.1",
    "react-redux": "^5.0.1",
    "react-router": "^3.0.0",
    "react-s-alert": "^1.2.2",
    "react-select": "^1.0.0-rc.2",
    "redux": "^3.6.0",
    "redux-promise": "^0.5.3",
    "tether": "^1.4.0"
  },
  "devDependencies": {
    "babel-core": "^6.21.0",
    "babel-loader": "^6.2.10",
    "babel-preset-es2015": "^6.18.0",
    "babel-preset-react": "^6.16.0",
    "babel-preset-stage-0": "^6.16.0",
    "css-loader": "^0.26.1",
    "extract-text-webpack-plugin": "^1.0.1",
    "file-loader": "^0.9.0",
    "node-sass": "^4.2.0",
    "react-hot-loader": "^1.3.1",
    "sass-loader": "^4.1.1",
    "style-loader": "^0.13.1",
    "url-loader": "^0.5.7",
    "webpack": "^1.14.0"
  }
ryanaleksander commented 7 years ago

I tried using Editor in another component and the same issue persisted. I'm also having problem with customizing toolbar. Not sure if I'm doing it right.

Uncaught (in promise) TypeError: Cannot read property 'className' of undefined
    at http://localhost:3000/assets/js/bundle.js:46800:3998
    at Array.map (native)
    at e.value (http://localhost:3000/assets/js/bundle.js:46800:3854)
    at e.value (http://localhost:3000/assets/js/bundle.js:46800:4942)
    at http://localhost:3000/assets/js/bundle.js:15805:22
    at measureLifeCyclePerf (http://localhost:3000/assets/js/bundle.js:15084:13)
    at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (http://localhost:3000/assets/js/bundle.js:15804:26)
    at ReactCompositeComponentWrapper._renderValidatedComponent (http://localhost:3000/assets/js/bundle.js:15831:33)
    at ReactCompositeComponentWrapper.performInitialMount (http://localhost:3000/assets/js/bundle.js:15371:31)
    at ReactCompositeComponentWrapper.mountComponent (http://localhost:3000/assets/js/bundle.js:15267:22)
(anonymous) @ react-draft-wysiwyg.js:37
value @ react-draft-wysiwyg.js:37
value @ react-draft-wysiwyg.js:37
(anonymous) @ ReactCompositeComponent.js:796
measureLifeCyclePerf @ ReactCompositeComponent.js:75
_renderValidatedComponentWithoutOwnerOrContext @ ReactCompositeComponent.js:795
_renderValidatedComponent @ ReactCompositeComponent.js:822
performInitialMount @ ReactCompositeComponent.js:362
mountComponent @ ReactCompositeComponent.js:258
mountComponent @ ReactReconciler.js:46
mountChildren @ ReactMultiChild.js:238
_createInitialChildren @ ReactDOMComponent.js:697
mountComponent @ ReactDOMComponent.js:516
mountComponent @ ReactReconciler.js:46
mountChildren @ ReactMultiChild.js:238
_createInitialChildren @ ReactDOMComponent.js:697
mountComponent @ ReactDOMComponent.js:516
mountComponent @ ReactReconciler.js:46
performInitialMount @ ReactCompositeComponent.js:371
mountComponent @ ReactCompositeComponent.js:258
mountComponent @ ReactReconciler.js:46
mountChildren @ ReactMultiChild.js:238
_createInitialChildren @ ReactDOMComponent.js:697
mountComponent @ ReactDOMComponent.js:516
mountComponent @ ReactReconciler.js:46
mountChildren @ ReactMultiChild.js:238
_createInitialChildren @ ReactDOMComponent.js:697
mountComponent @ ReactDOMComponent.js:516
mountComponent @ ReactReconciler.js:46
mountChildren @ ReactMultiChild.js:238
_createInitialChildren @ ReactDOMComponent.js:697
mountComponent @ ReactDOMComponent.js:516
mountComponent @ ReactReconciler.js:46
mountChildren @ ReactMultiChild.js:238
_createInitialChildren @ ReactDOMComponent.js:697
mountComponent @ ReactDOMComponent.js:516
mountComponent @ ReactReconciler.js:46
_updateRenderedComponent @ ReactCompositeComponent.js:765
_performComponentUpdate @ ReactCompositeComponent.js:724
updateComponent @ ReactCompositeComponent.js:645
receiveComponent @ ReactCompositeComponent.js:547
receiveComponent @ ReactReconciler.js:125
_updateRenderedComponent @ ReactCompositeComponent.js:754
_performComponentUpdate @ ReactCompositeComponent.js:724
updateComponent @ ReactCompositeComponent.js:645
performUpdateIfNecessary @ ReactCompositeComponent.js:561
performUpdateIfNecessary @ ReactReconciler.js:157
runBatchedUpdates @ ReactUpdates.js:150
perform @ Transaction.js:140
perform @ Transaction.js:140
perform @ ReactUpdates.js:89
flushBatchedUpdates @ ReactUpdates.js:172
closeAll @ Transaction.js:206
perform @ Transaction.js:153
batchedUpdates @ ReactDefaultBatchingStrategy.js:62
enqueueUpdate @ ReactUpdates.js:200
enqueueUpdate @ ReactUpdateQueue.js:24
enqueueSetState @ ReactUpdateQueue.js:209
ReactComponent.setState @ ReactComponent.js:63
onStateChange @ connectAdvanced.js:217
notify @ Subscription.js:30
notifyNestedSubs @ Subscription.js:65
onStateChange @ connectAdvanced.js:210
dispatch @ createStore.js:186
dispatch @ VM1450:2
(anonymous) @ index.js:28
(anonymous) @ Profile.jsx:24
ReactCompositeComponent.js:745Uncaught (in promise) TypeError: Cannot read property '_currentElement' of null
    at ReactCompositeComponentWrapper._updateRenderedComponent (ReactCompositeComponent.js:745)
    at ReactCompositeComponentWrapper._performComponentUpdate (ReactCompositeComponent.js:724)
    at ReactCompositeComponentWrapper.updateComponent (ReactCompositeComponent.js:645)
    at ReactCompositeComponentWrapper.receiveComponent (ReactCompositeComponent.js:547)
    at Object.receiveComponent (ReactReconciler.js:125)
    at Object.updateChildren (ReactChildReconciler.js:109)
    at ReactDOMComponent._reconcilerUpdateChildren (ReactMultiChild.js:208)
    at ReactDOMComponent._updateChildren (ReactMultiChild.js:312)
    at ReactDOMComponent.updateChildren (ReactMultiChild.js:299)
    at ReactDOMComponent._updateDOMChildren (ReactDOMComponent.js:936)
 this.editorToolbar = {
      inline: {
        options: ["bold", "italic", "underlined", "strikethrough"],
        className: "editor-toolbar",
      },
      options: ["inline"]
    }
<Editor editorState={this.state.description} onChange={this.onDescriptionChange.bind(this)}
                      editorStyle={{height: "200px", border: "1px solid #f4f4f4"}} toolbar={this.editorToolbar}
              />
jpuri commented 7 years ago

On thing underlined is typo.

jpuri commented 7 years ago

Please use onEditorStateChange instead of onChange. Refer docs: https://jpuri.github.io/react-draft-wysiwyg/#/docs

ryanaleksander commented 7 years ago

Thank you, it works perfectly now. Silly me for not reading the docs carefully

antonsavchenko94 commented 7 years ago

@jpuri, I have the same propblem. And it occurs when I try to turn html to editorState TypeError: editorState.getImmutable is not a function at Function.set (modules.js?hash=48bcc6b…:59909) at e.Q.createEditorState (modules.js?hash=48bcc6b…:57848) at e.value (modules.js?hash=48bcc6b…:57848) at modules.js?hash=48bcc6b…:21872 at measureLifeCyclePerf (modules.js?hash=48bcc6b…:21599) at ReactCompositeComponentWrapper.performInitialMount (modules.js?hash=48bcc6b…:21871) at ReactCompositeComponentWrapper.mountComponent (modules.js?hash=48bcc6b…:21782) at Object.mountComponent (modules.js?hash=48bcc6b…:14707) at ReactDOMComponent.mountChildren (modules.js?hash=48bcc6b…:20891) at ReactDOMComponent._createInitialChildren (modules.js?hash=48bcc6b…:18107)

antonsavchenko94 commented 7 years ago

My component: import React, { Component } from 'react'; import { Panel } from 'react-bootstrap'; import { Editor } from 'react-draft-wysiwyg'; import { stateToHTML } from 'draft-js-export-html'; import { stateFromHTML } from 'draft-js-import-html'; import { compose } from "react-komposer"; import { getTrackerLoader } from "../../../../../lib/helpers"; import TestDescriptions from "../../../../api/lists/descriptions";

class CreateDescription extends Component { constructor(props) { super(props); if(this.props.description) { console.log(this.props.description); this.state = { editorState: stateFromHTML(this.props.description.html) } } }

onEditorStateChange(value) {
    let html = stateToHTML(value.getCurrentContent());
    console.log(this.props);
    Meteor.call("description.update", html, this.props.title);
}
goToDescriptions() {
    FlowRouter.go('/admin/descriptions');
}
render() {
    const {editorState}  = this.state
    return (
        <div className="container">
          <Panel header="Manage your descriptions">
              <h3>Title:{this.props.title}</h3>
              <Editor
                  editorState={editorState}
                  toolbarClassName="home-toolbar"
                  wrapperClassName="home-wrapper"
                  editorClassName="home-editor"
                  onEditorStateChange={this.onEditorStateChange.bind(this)}
              />
              <button onClick={this.goToDescriptions}>FINISH</button>
          </Panel>
        </div>
    );
}

}

const composer = ( props, onData ) => { const subscription = Meteor.subscribe('descriptions'); if ( subscription.ready() ) { console.log('description'); let description = TestDescriptions.findOne({title: props.title}); onData( null, {description} ); } };

export default compose(getTrackerLoader(composer))( CreateDescription ); `

rloomba commented 7 years ago

@jpuri any thoughts on potentially adding onChange in addition to onEditorStateChange? This seems to be the standard for react components...and spent a bit of time debugging this. Happy to submit a PR if you think that's OK?

AlexanderTserkovniy commented 6 years ago

@rloomba hey any updates from your side? Have the same issue.

rloomba commented 6 years ago

@AlexanderTserkovniy does using onEditorStateChange instead of onChange work?

AlexanderTserkovniy commented 6 years ago

@rloomba no mate, did not. But I found source of issue. Thanks. I was just setting incorrect value right after update and first update occurs on focus.

indefinitelee commented 4 years ago

am also having this issue "react-draft-wysiwyg": "^1.14.4", "draft-js": "^0.11.4", "react": "^16.8.6",

sakinaboriwala commented 4 years ago

This worked for me: https://github.com/jpuri/react-draft-wysiwyg/issues/255#issuecomment-290549423