2
votes

I'm trying to read data from database and then render to the DOM via react. For the input, I used draft.js and run convertToRaw on it before saving to the db. However, when I run convertFromRaw and render, I get this error in the console: "Uncaught TypeError: Cannot read property 'blocks' of undefined". This is my first time using draft.js so I'm not sure what I'm doing wrong. Can someone please help? Thank you so much!

//App.js


import React, {
  Component
}
from 'react';
import Blogs from './blogs';
import {
  Editor, EditorState, convertToRaw
}
from 'draft-js'
  // include horizon client
const Horizon = require('@horizon/client');
const horizon = Horizon({
  secure: false
});
// init blogs collection in rethinkdb
const blogger = horizon('blogs')

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      title: false,
      author: false,
      editorState: EditorState.createEmpty()
    }
  }

  // watch form values for change
  handleChangeTitle(event) {
    this.setState({
      title: event.target.value
    });
  }
  handleChangeAuthor(event) {
    this.setState({
      author: event.target.value
    });
  }
  handleChangeBody(editorState) {
    this.setState({
      editorState
    });
  }

  writeBlog() {
    // check for empty string and return error to user
    if (this.state.title === false || this.state.author === false || this.state.body === false) {
      alert('Invalid Submission: One or more fields are empty');
      return;
    }
    let blog = {
      title: this.state.title,
      author: this.state.author,
      editorState: convertToRaw(this.state.editorState.getCurrentContent())
    };
    // store the inputs in the database
    blogger.store(blog);
  }

  render() {
    return ( < form >
      < div className = "center" >
      < Blogs blogger = {
        blogger
      }
      />
                    <div className="writer">
                    <div className="basic-inputs">
                        <div className="input-unit">
                            <label>Title</label >
      < input onChange = {
        this.handleChangeTitle.bind(this)
      } > < /input>
                        </div >
      < div className = "input-unit" >
      < label > Author < /label>
                            <input onChange={this.handleChangeAuthor.bind(this)}></input >
      < /div>
                    </div >
      < label > Blog < /label>
                    <Editor onChange={this.handleChangeBody.bind(this)} editorState={this.state.editorState} / >
      < button onClick = {
        this.writeBlog.bind(this)
      } > Post < /button>
                    </div >
      < /div>
            </form >
    );
  }
}

export
default App;

import React, { Component } from 'react';
import {convertFromRaw} from 'draft-js'

export default class Blog extends Component {
    constructor(props) {
        super(props)
        this.props = props;

    }

    render() {
        return (
            <div className="blog-container">
            <h2 className="title">{this.props.blg.title}</h2>
            <h4 className="author">{this.props.blg.author}</h4>
            <p className="body">{convertFromRaw(this.props.blg.body)}</p>
            </div>
        );
    }
}
1
what does this.props.blg.body return ?finalfreq
It returns the state of the draftjs input as an object from the databaseohenecoker
what happens if you do convertFromRaw(JSON.parse(this.props.blg.body))finalfreq
Hmm I'mg getting an error in the console; "Uncaught SyntaxError: Unexpected token u in JSON at position 0"ohenecoker

1 Answers

1
votes

I have been using these functions to convert the ContentState into raw, and then from raw object back into an EditorState.

You might need to stringify your editorState when converting it to raw. Then you might need to parse it when you try to use it in your blog component.

/**
 * @param { EditorState } editorState
 * @returns { object }
 */
export const toRaw = editorState => {
  return convertToRaw(editorState.getCurrentContent());
};

/**
 * @param { EditorState } editorState
 * @param { object } raw
 * @returns { EditorState }
 */
export const fromRaw = (editorState, raw) => {
  return EditorState.push(editorState, convertFromRaw(raw), 'update-state');
};

Im also getting the EditorState from localStorage like this:

  componentWillMount() {
    if (!window.localStorage) {
      return;
    }
    const _editorState = localStorage.getItem('editorState');
    if (_editorState) {
      const parsedEditorState = JSON.parse(_editorState);
      const editorState = EditorState.push(
        this.state.editorState,
        convertFromRaw(parsedEditorState),
        'update-state'
      );
      this.setState({ editorState });
    }
  }