将<Component />与危险地使用SetInnerHTML

时间:2019-10-13 07:35:37

标签: javascript html reactjs

首先,我确实尝试查看了一些类似的问题,但是找不到最适合我的情况的问题,因为我需要多个参数。

我有一个包含原始HTML数据的变量,包括一个较长的段落,如果该段落太长,则需要截断。为了简化生活,我使用一个模块来处理这个问题(read-more-react)。 read-more-react要求填写一些字段,包括文本本身,以及其他一些字段(例如,最小和最大字符),然后截断。

从Gatsby解析原始HTML数据的建议方法是使用dangerouslySetInnerHTML,但是在包含组件时遇到了一些问题。我尝试使用不带dangerouslySetInnerHTML的read-more-react模块。它可以工作,但仅输出原始HTML“ <h1>A title</h1><p>Some copy...</p>等),而无需实际解析。

相反,我尝试了这个;


    <div
      className="md container"
      dangerouslySetInnerHTML={{
        __html: `
          <ReadMoreReact
            text=${htmlContent}
            min="180"
            ideal="190"
            max="200"
            readMoreText="Read more"
          />
        `,
      }}
    />

但是我得到一个奇怪的输出;

  

标题

     

某些副本

     

min="180" ideal="190" max="200" readMoreText="Read more" />

因此,这显然行不通。有人可以建议解决方法吗?

2 个答案:

答案 0 :(得分:0)

read-more-react似乎只处理文本,而不处理html。
为了将段落与其余部分分开并提取其文本内容,您可能应该在将html字符串传递给ReadMoreReact组件之前先对其进行解析。
实际上,您可以使用DOM做到这一点:

const htmlString = "<h1>This is the title</h1><p>The innerText property of the HTMLElement interface represents the \"rendered\" text content of a node and its descendants. As a getter, it approximates the text the user would get if they highlighted the contents of the element with the cursor and then copied it to the clipboard.</p>"

const dummyElement = document.createElement('div')
dummyElement.innerHTML = htmlString;
const titleText = dummyElement.querySelector('h1').innerText
const pText = dummyElement.querySelector('p').innerText

console.log('title ==>', titleText);
console.log('p ==>', pText);

答案 1 :(得分:0)

问题是dangerouslySetInnerHTML需要一串普通的HTML元素。相反,您尝试传递无效HTML的React节点(另外ReadMoreReact返回array字符串,这也是无效的)。相反,您可以使用它们的trimText实用程序功能,该功能可以完成您期望的工作。

这些示例使用了一些高级ES5 +功能:

工作示例(使用钩子):

Edit Trim HTML Text

import React from "react";
import { render } from "react-dom";
import trimText from "./utils/trimText";
import "./styles.css";

const htmlText =
  "<h2 style='display:inline;'>Lorem ipsum</h2> dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.";

function App() {
  const [state, setState] = React.useState({
    showOriginalHTML: false,
    originalHTML: htmlText,
    trimmedHTML: trimText(htmlText, 20, 200)[0]
  });

  const handleShowText = React.useCallback(() => {
    setState(prevState => ({
      ...prevState,
      showOriginalHTML: !prevState.showOriginalHTML
    }));
  }, [setState]);

  return (
    <div className="container">
      <div
        className="text"
        dangerouslySetInnerHTML={{
          __html: `${
            !state.showOriginalHTML ? state.trimmedHTML : state.originalHTML
          }`
        }}
      />
      <button className="read-more" onClick={handleShowText}>
        {!state.showOriginalHTML ? "read more" : "show less"}
      </button>
    </div>
  );
}

render(<App />, document.getElementById("root"));

工作示例(使用类):

Edit Trim HTML Text - Classes

import React from "react";
import { render } from "react-dom";
import trimText from "./utils/trimText";
import "./styles.css";

const htmlText =
  "<h2 style='display:inline;'>Lorem ipsum</h2> dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.";

class App extends React.Component {
  state = {
    showOriginalHTML: false,
    originalHTML: htmlText,
    trimmedHTML: trimText(htmlText, 20, 200)[0]
  };

  handleShowText = () =>
    this.setState(prevState => ({
      showOriginalHTML: !prevState.showOriginalHTML
    }));

  render = () => {
    const { originalHTML, showOriginalHTML, trimmedHTML } = this.state;

    return (
      <div className="container">
        <div
          className="text"
          dangerouslySetInnerHTML={{
            __html: `${!showOriginalHTML ? trimmedHTML : originalHTML}`
          }}
        />
        <button className="read-more" onClick={this.handleShowText}>
          {!showOriginalHTML ? "read more" : "show less"}
        </button>
      </div>
    );
  };
}

render(<App />, document.getElementById("root"));