12
votes

I'm using Draft.js to implement a text editor. I want to save the content of the editor to a DB and later retrieve it and inject it in an editor again, e.g. when revisiting the editor page.

First, these are the relevant imports

import { ContentState, EditorState, convertToRaw, convertFromRaw } from 'draft-js';

How I Save the Data to the DB (located in a parent Component)

saveBlogPostToStore(blogPost) {
    const JSBlogPost = { ...blogPost, content: convertToRaw(blogPost.content.getCurrentContent())};
    this.props.dispatch(blogActions.saveBlogPostToStore(JSBlogPost));
}

Now when I check the DB, I get the following Object:

[{"_id":null,"url":"2016-8-17-sample-title","title":"Sample Title","date":"2016-09-17T14:57:54.649Z","content":{"blocks":[{"key":"4ads4","text":"Sample Text Block","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[]}]},"author":"Lukas Gisder-Dubé","__v":0,"tags":[]}]

So far so good I guess, I tried some other stuff and the Object in the Database is definitely converted. For example, when I save the content without calling the convertToRaw()-method, there are a lot more fields.

Setting the Data as new EditorState

To retrieve the Data from the DB and set it as EditorState, I also tried a lot. The following is my best guess:

constructor(props) {
    super(props);
    const DBEditorState = this.props.blogPost.content;
    console.log(DBEditorState); // logs the same Object as above
    this.state = { ...this.props.blogPost, content: EditorState.createWithContent(
        convertFromRaw(DBEditorState)
    )};
}

When rendering the component i get the following error:

convertFromRawToDraftState.js:38 Uncaught TypeError: Cannot convert undefined or null to object

Any help is greatly appreciated!

1
What is convertFromRaw function doing? - Kafo
It converts the raw JSON data to a ContentState Object usable in EditorState. See facebook.github.io/draft-js/docs/… - gisderdube
It seems that you are giving the function an undefined or null object. constructor is going to be run once when the component is mounted. Any passes of props to it after mounting won't hit he conversion again. The conversion should probably go to componentDidMount instead of constructor. - Kafo
Add some log and make sure the raw content in convertFromRaw is the same JSON string from convertToRaw. - Jiang YD
@HusseinAlkaf Thank you for your advice, unfortunately this didn't resolve the problem. Also, you don't have to set the content, depending on the props, in componentDidMount(). You can directly set it in the constructor. JiangYD: not really helpful. - gisderdube

1 Answers

21
votes

Seems that MongoDB/Mongoose didn't like the raw content from the ContentState. Converting the data to a String before sending it to the DB did the trick:

Saving the ContentState to the DB

    saveBlogPostToStore(blogPost) {
    const JSBlogPost = { ...blogPost, content: JSON.stringify(convertToRaw(blogPost.content.getCurrentContent()))};
    this.props.dispatch(blogActions.saveBlogPostToStore(JSBlogPost));
}

Using the data from the DB

constructor(props) {
    super(props);
    const DBEditorState = convertFromRaw(JSON.parse(this.props.blogPost.content));

    this.state = { ...this.props.blogPost, content: EditorState.createWithContent(
        DBEditorState
    )};
}