5

I'm using react-quill and I have the data saving, however, I'm running into a few issues.

  1. How do I go about rendering out the contents after the save? Currently, I'm just getting the HTML back

  1. I'm getting the following on the edit page

Here is my component

import React, { Component } from "react";
import { withRouter } from "react-router-dom";
import "react-quill/dist/quill.snow.css";
import ReactQuill from "react-quill";
import swal from "sweetalert";
import axios from "axios";

import AuthService from "../../Auth/AuthService";
import withAuth from "../../Auth/withAuth";
const Auth = new AuthService();

class Edit extends Component {
  constructor(props) {
    super(props);
    this.state = {
      journal: {}
    };
  }

  componentDidMount() {
    const journalId = this.props.match.params.id;
    axios
      .get("/api/journals/" + journalId)
      .then(result => {
        this.setState({ journal: result.data });
      })
      .catch(error => {
        console.error(error);
      });
  }

  modules = {
    toolbar: [
      [{ header: [1, 2, false] }],
      ["bold", "italic", "underline", "strike", "blockquote"],
      [
        { list: "ordered" },
        { list: "bullet" },
        { indent: "-1" },
        { indent: "+1" }
      ],
      ["link", "image"],
      ["clean"]
    ]
  };

  formats = [
    "header",
    "bold",
    "italic",
    "underline",
    "strike",
    "blockquote",
    "list",
    "bullet",
    "indent",
    "link",
    "image"
  ];

  onChange = e => {
    const state = this.state.journal;
    state[e.target.name] = e.target.value;
    this.setState({ journal: state });
  };

  handleQuillChange = value => {
    this.setState({ content: value });
  };

  onSubmit = e => {
    e.preventDefault();
    const journalId = this.props.match.params.id;
    const { title, content } = this.state.journal;

    let config = {
      headers: { Authorization: "bearer " + Auth.getToken() }
    };

    let body = {
      title,
      content
    };

    axios
      .put("/api/journals/" + journalId, body, config)
      .then(result => {
        swal({
          title: "Success",
          text: `You have edited the journal ${title}`,
          icon: "success",
          button: "OK"
        });
        this.props.history.push("/journals/" + journalId);
      })
      .catch(error => {
        swal({
          title: "Error",
          text: `${error}`,
          icon: "error",
          button: "Try again"
        });
      });
  };

  render() {
    return (
      <>
        <div className='block md:flex md:flex-column h-full'>
          <div className='p-12 w-full text-center text-gray-800'>
            <h1 className='title mb-10'>Edit a journal</h1>

            <form className='w-full m-auto max-w-lg' onSubmit={this.onSubmit}>
              <div className='flex flex-wrap mb-4'>
                <label htmlFor='title'>Title:</label>
                <input
                  type='text'
                  name='title'
                  defaultValue={this.state.journal.title}
                  onChange={this.onChange}
                  placeholder='Title'
                />
              </div>

              <div className='flex flex-wrap'>
                <label htmlFor='description'>content:</label>
                <ReactQuill
                  name='content'
                  className='h-64'
                  value={this.state.content}
                  onChange={this.handleQuillChange}
                  theme='snow'
                  modules={this.modules}
                  formats={this.formats}
                />
              </div>

              <div className='flex'>
                <button type='submit' className='btn w-full'>
                  Submit
                </button>
              </div>
            </form>
          </div>
        </div>
      </>
    );
  }
}

export default withAuth(withRouter(Edit));

So any help would be great on solving both issues.

  • In ReactJS, you can use the built-in dangerouslySetInnerHTML prop on a JSX element to set the inner HTML to a string that contains potentially unsafe content. This should be used with caution, as it can open your application up to cross-site scripting (XSS) attacks if the content is not properly sanitized. You can you DOMPurify library to sanitize the htmlString. `` – Nuwa Jan 22 '23 at 17:16

5 Answers5

4
  1. To render the content without HTML markup. You can use npm package htmr to render the content of React-quill without the HTML markup.

  2. By doing the above thing might solve your issue, If that doesn't work , try escaping the html entities before rendering the content by doing

const decodedHtml = htmlEntities.decode(html)
// or
const decodedHtml = html.replace(/&lt;/g, '<').replace(/&gt;/g, '>')

return htmr(decodedHtml)

See this for reference How to render the content of React Quill without the html Markup

jarivak
  • 828
  • 13
  • 28
1

In ReactJS, you can use the built-in dangerouslySetInnerHTML prop on a JSX element to set the inner HTML to a string that contains potentially unsafe content. This should be used with caution, as it can open your application up to cross-site scripting (XSS) attacks if the content is not properly sanitized.

You can you dompurify library to sanitize the htmlString.

import DOMPurify from 'dompurify';

const htmlString = '<p>This is some <strong>unsafe</strong> HTML.</p>';
const cleanedHTML = DOMPurify.sanitize(htmlString);

return <div dangerouslySetInnerHTML={{ __html: cleanedHTML }} />

Thnx :)

Nuwa
  • 461
  • 4
  • 10
0

Not sure starting from what version, but currently React JS escapes HTML by default.

Exceptions.

humkins
  • 9,635
  • 11
  • 57
  • 75
0
const newStr = htmlStr.replace(/(<([^>]+)>)/ig, '');
return newStr;
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
  • 1
    Please read [How do I write a good answer?](https://stackoverflow.com/help/how-to-answer). While this code block may answer the OP's question, this answer would be much more useful if you explain how this code is different from the code in the question, what you've changed, why you've changed it and why that solves the problem without introducing others. – Saeed Zhiany Aug 16 '22 at 13:34
0

I'm not sure if OP is intending to render the actual HTML as well (so if the user bolds the text in react-quill, it will show up as bolded).

You can do that with:

<div dangerouslySetInnerHTML={{ __html: htmlString }}/>

Note that dangerously. It does basically give the user the ability to enter broken html and break your website. So you have to be sure that you trust the user.

NotSimon
  • 1,795
  • 1
  • 21
  • 31