user8331511
user8331511

Reputation:

Escape html in react

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.

Upvotes: 6

Views: 19529

Answers (5)

NuwaT
NuwaT

Reputation: 461

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 :)

Upvotes: 1

NotSimon
NotSimon

Reputation: 1815

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.

Upvotes: 1

Deodeep kunj
Deodeep kunj

Reputation: 1

const newStr = htmlStr.replace(/(<([^>]+)>)/ig, '');
return newStr;

Upvotes: 0

humkins
humkins

Reputation: 10697

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

Exceptions.

Upvotes: 0

jarivak
jarivak

Reputation: 858

  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

Upvotes: 4

Related Questions