[英]Replace part of html string with React.js component and render (without dangerouslySetInnerHTML)
I'm working with Node.js/React.js client that fetch data from WordPress API and I've faced quite tricky problem. 我正在使用从WordPress API获取数据的Node.js / React.js客户端,我遇到了相当棘手的问题。 But hopefully You can help me out!
但希望你可以帮助我! :)
:)
So I have this kind of data as a string from WordPress API (single page content): 所以我把这种数据作为WordPress API的字符串(单页内容):
"<h1>Curabitur turpis.</h1>
<p>Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Praesent blandit laoreet nibh. Aenean commodo ligula eget dolor. Donec vitae sapien ut libero venenatis faucibus.</p>
[gravityform id=”42″ title=”true” description=”true”]
<h2>Donec vitae orci sed</h2>
<p><strong>Suspendisse faucibus</strong>, nunc et pellentesque egestas, lacus ante convallis tellus, vitae iaculis lacus elit id tortor. Vestibulum rutrum, mi nec elementum vehicula, eros quam gravida nisl, id fringilla neque ante vel mi.</p>
<blockquote><p>Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Aliquam lobortis. In turpis.</p></blockquote>
<ul><li>item</li><li>item</li><li>item</li></ul>"
What I need to do is replace the shortcode [gravityform id=”42″ title=”true” description=”true”]
我需要做的是替换短代码
[gravityform id=”42″ title=”true” description=”true”]
[gravityform id=”42″ title=”true” description=”true”]
[gravityform id=”42″ title=”true” description=”true”]
to React component <GravityForm />
with wanted event handlers etc. and render other html elements as is. [gravityform id=”42″ title=”true” description=”true”]
使用想要的事件处理程序等来反应组件<GravityForm />
呈现其他html元素。
I'm doing the replacing like: 我正在做的更换像:
export const replaceGravityFormShortcode = html => {
if(!html) return html;
const gravityFormRegexp = /\[gravityform id=.([0-9]{1,}).*?\]/g;
return replace(
html,
gravityFormRegexp,
function (fullMatch, id) {
return <GravityForm key={id} formId={id} />;
}
);
};
So replacing [shortcodes] with React components is already covered but after that the html data looks like this: [ 0:"<h1>Curabitur turpis.</h1><p>Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Praesent blandit laoreet nibh. Aenean commodo ligula eget dolor. Donec vitae sapien ut libero venenatis faucibus.</p>" 1:Object (GravityForm-component) 2:"<h2>Donec vitae orci sed</h2><p><strong>Suspendisse faucibus</strong>, nunc et pellentesque egestas, lacus ante convallis tellus, vitae iaculis lacus elit id tortor. Vestibulum rutrum, mi nec elementum vehicula, eros quam gravida nisl, id fringilla neque ante vel mi.</p><blockquote><p>Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Aliquam lobortis. In turpis.</p></blockquote><ul><li>item</li><li>item</li><li>item</li></ul>" ]
因此,已经涵盖了用React组件替换[shortcodes],但之后html数据看起来像这样:
[ 0:"<h1>Curabitur turpis.</h1><p>Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Praesent blandit laoreet nibh. Aenean commodo ligula eget dolor. Donec vitae sapien ut libero venenatis faucibus.</p>" 1:Object (GravityForm-component) 2:"<h2>Donec vitae orci sed</h2><p><strong>Suspendisse faucibus</strong>, nunc et pellentesque egestas, lacus ante convallis tellus, vitae iaculis lacus elit id tortor. Vestibulum rutrum, mi nec elementum vehicula, eros quam gravida nisl, id fringilla neque ante vel mi.</p><blockquote><p>Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Aliquam lobortis. In turpis.</p></blockquote><ul><li>item</li><li>item</li><li>item</li></ul>" ]
So obviously that ain't going to work within render()
because 很明显,这不会在
render()
工作,因为
dangerouslySetInnerHTML
it looks like this ( <GravityForm />
is [object Object]
) dangerouslySetInnerHTML-screenshot dangerouslySetInnerHTML
它看起来像这样( <GravityForm />
是[object Object]
) dangerouslySetInnerHTML-screenshot So is there any reasonable solution for this problem? 那么这个问题有什么合理的解决方案吗? Or should this be approached from some different perspective?
或者应该从不同的角度来看待这个问题?
Thanks for your help! 谢谢你的帮助!
@joy Yes, your solution is changing the html string to React Components, but it still doesn't solve the html escape issue. @joy是的,您的解决方案是将html字符串更改为React Components,但它仍然无法解决html转义问题。 So I still have output like ( screenshot )
所以我仍然有输出( 截图 )
<h1>Curabitur turpis.</h1><p>Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Praesent blandit laoreet nibh. Aenean commodo ligula eget dolor. Donec vitae sapien ut libero venenatis faucibus.</p>
<h2>Donec vitae orci sed</h2><p><strong>Suspendisse faucibus</strong>, nunc et pellentesque egestas, lacus ante convallis tellus, vitae iaculis lacus elit id tortor. Vestibulum rutrum, mi nec elementum vehicula, eros quam gravida nisl, id fringilla neque ante vel mi.</p><blockquote><p>Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Aliquam lobortis. In turpis.</p></blockquote><ul><li>item</li><li>item</li><li>item</li></ul>
But is it even possible to render that html without parsing the html elements one by one from the string? 但是,甚至可以在不从字符串中逐个解析html元素的情况下呈现该html吗?
So I finally figured out ~working~ solution for this case. 所以我终于找到了〜工作〜这个案例的解决方案。
[ 0:Object 1:Object 2:"[gravityform id=”42″ title=”true” description=”true”]" 3:Object 4:Object 5:Object 6:Object ]
[ 0:Object 1:Object 2:"[gravityform id=”42″ title=”true” description=”true”]" 3:Object 4:Object 5:Object 6:Object ]
replaceGravityFormShortcodesFromArrayOfObjects(arrayOfObjects)
, replace [gravityform id=”42″ title=”true” description=”true”]
with <GravityForm />
and then just render the data replaceGravityFormShortcodesFromArrayOfObjects(arrayOfObjects)
,用<GravityForm />
替换[gravityform id=”42″ title=”true” description=”true”]
,然后只渲染数据 export const replaceGravityFormShortcodesFromArrayOfObjects =(dataArray) => {
if(!dataArray) return dataArray;
const gravityFormRegexp = /\[gravityform id=.([0-9]{1,}).*?\]/g;
forEach(dataArray, (value, index) => {
if(typeof value === 'string'){
const temp = replace(
value,
gravityFormRegexp,
function (fullMatch, id) {
return <GravityForm key={id} formId={id} />;
}
);
if(temp.length === 1 && isObject(temp[0])){
dataArray = [
...dataArray.slice(0, index),
temp[0],
...dataArray.slice(index + 1),
];
}
}
}
return dataArray;
};
BUT this works only if html structure is one level deep. 但是,这只能如果HTML结构是一个级别深度。 If
"[gravityform id=”42″ title=”true” description=”true”]"
is inside React element props.children
, it's get trickier and I haven't figured out working solution yet. 如果
"[gravityform id=”42″ title=”true” description=”true”]"
在React元素props.children
里面,它props.children
棘手,我还没有想出工作解决方案。
I encountered exactly the same issue, and here is my solution: 我遇到了完全相同的问题,这是我的解决方案:
Define the string: 定义字符串:
const s = `<h1>Curabitur turpis.</h1>
<p>Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Praesent blandit laoreet nibh. Aenean commodo ligula eget dolor. Donec vitae sapien ut libero venenatis faucibus.</p>
[gravityform id=”42″ title=”true” description=”true”]
<h2>Donec vitae orci sed</h2>
<p><strong>Suspendisse faucibus</strong>, nunc et pellentesque egestas, lacus ante convallis tellus, vitae iaculis lacus elit id tortor. Vestibulum rutrum, mi nec elementum vehicula, eros quam gravida nisl, id fringilla neque ante vel mi.</p>
<blockquote><p>Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Aliquam lobortis. In turpis.</p></blockquote>
<ul><li>item</li><li>item</li><li>item</li></ul>`
Split the string by [*]
: 用
[*]
拆分字符串:
const normalText = s.split(/\[[\s\S]+\]/g)
Extract the ids: 提取ID:
let ids = [];
const re = /\[gravityform id=.*([0-9]{1,}).*\]/g;
s.replace(re, (fullMatch, id) => {
ids.push(id)
})
Now the arrays normalText
and ids
has the content we want to concatinate. 现在,数组
normalText
和ids
具有我们想要连接的内容。 Simply concat them: 简单地说:
const output = normalText.map((text, index) => {
<div>
{text}
<GravityForm key={ids[index]} formId={ids[index]} />
</div>
})
// Then put `output` in the `render` function
You may want to tune the regular expression a bit, as your string contains some unicode like ”
您可能希望稍微调整正则表达式,因为您的字符串包含一些类似于
”
字符串”
. 。 Either remove them or escape them first.
要么删除它们要么先逃脱它们。
In order not to escape HTML: 为了不逃避HTML:
<div dangerouslySetInnerHTML={{ __html: text }}/>
Reference: https://facebook.github.io/react/docs/dom-elements.html 参考: https : //facebook.github.io/react/docs/dom-elements.html
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.