替换<a> with React <link/> in text

时间:2019-02-20 19:50:41

标签: javascript reactjs react-router jsx

in my React app I am getting some HTML from another server (Wikipedia) and - in this text - want to replace all the links with react-router links.

What I have come up with is the following code:

// Parse HTML with JavaScript DOM Parser
let parser = new DOMParser();
let el = parser.parseFromString('<div>' + html + '</div>', 'text/html');

// Replace links with react-router links
el.querySelectorAll('a').forEach(a => {
  let to = a.getAttribute('href');
  let text = a.innerText;
  let link = <Link to={to}>{text}</Link>;
  a.replaceWith(link);
});
this.setState({
  html: el.innerHTML
})

Then later in render() I then inserted it into the page using

<div dangerouslySetInnerHTML={{__html: this.state.html}} />

The problem is that React JSX is not a native JavaScript element thus not working with replaceWith. I also assume that such a Link object can not be stored as text and then later be restored using dangerouslySetInnerHTML.

So: what is the best way to do this method? I want to keep all the various elements around the link so I cannot simply loop through the links in render()

3 个答案:

答案 0 :(得分:2)

嗯,您确实需要使用Link 选项1:

import { renderToString } from 'react-dom/server';
el.querySelectorAll('a').forEach(a => {
  let to = a.getAttribute('href');
  let text = a.innerText;
  const link = renderToString(<Link to={to}>{text}</Link>);
  a.replaceWith(link);
});

选项2:使用html-react-parser

答案 1 :(得分:1)

您不能像这样渲染<Link>。 相反,您可以尝试另一种方法:

el.querySelectorAll('a').forEach((a) => {
    a.addEventListener('click', (event) => {
       event.preventDefault()
       const href = a.getAttribute('href');
       // use React Router to link manually to href
    })
})

当点击<a>时,您将手动进行路由。

请参见Programmatically navigate using react router

答案 2 :(得分:1)

您可以利用 html-react-parser

的功能
import parse, { domToReact } from 'html-react-parser';
import { Link } from 'react-router-dom';    

function parseWithLinks(text) {
  const options = {
    replace: ({ name, attribs, children }) => {
      if (name === 'a' && attribs.href) {
        return <Link to={attribs.href}>{domToReact(children)}</Link>;
      }
    }
  };
      
  return parse(text, options);
}

然后像这样使用它:

const textWithRouterLinks = parseWithLinks('<a href="/home">Home page</a>');