Я получаю строку HTML из SharePoint, и мне нужно проанализировать и изменить данные и создать элемент реакции, который будет отображаться в моем приложении реакции.
По сути, у меня есть код (в виде строки), возвращаемый мне в формате, похожем на:
"
<div>
<div data-sp-canvasdataversion = "1">This could be a header</div>
<div data-sp-canvasdataversion = "1"><img src = "titleimage.jpg"></div>
<div data-sp-canvasdataversion = "1"><a href = "pdfLink.pdf">This is a link to a PDF</a></div>
</div>
"
и из этого мне нужно пройтись по дочерним элементам и создать новый элемент React, содержащий некоторые части того, что было возвращено, и некоторые новые части, такие как
<div>
<div data-sp-canvasdataversion = "1">This could be a header</div>
<div data-sp-canvasdataversion = "1"><img src = "titleimage.jpg"></div>
<PDFViewer file = {""pdfLink.pdf""}></PDFViewer>
</div>
Первоначально я использовал опасно SetInnerHTML, который работал, чтобы просто отображать данные, но теперь мне нужно удалить фрагмент html, создать элемент реакции на основе данных и ввести новый элемент обратно в код. Поскольку сейчас я пытаюсь вставить компонент, ванильный html не будет работать.
Я могу перебирать дочерние элементы, преобразовывая их в узел dom, но я не могу понять, как использовать узел или элемент dom в качестве дочернего элемента React Element.
Я пробовал:
let element = React.createElement('div', {}, HTMLString);
let node = document.createRange().createContextualFragment(HTMLString).firstChild;
let element = React.createElement('div', {}, node);
let node = document.createRange().createContextualFragment(HTMLString).firstChild;
let node2 = document.createElement("div");
node2.appendChild(node);
node2 = node2.firstElementChild as HTMLDivElement;
let element = React.createElement('div', {}, node2);
Ни один из них не работает должным образом и не дает мне ошибку Objects are not valid as a React child (found: [object HTMLDivElement]). или аналогичную.
Мне нужно что-то вроде:
let element = React.createElement('div');
let node = document.createRange().createContextualFragment(HTMLString).firstChild;
node.childNodes.forEach(child => {
if (...//child IS NOT pdf)
element.appendChild(child)
else if (...//child IS pdf){
...
element.appendChild(<PDFViewer file = "linktopdf.pdf">)
}
})
Тогда я ожидаю, что смогу использовать это в рендере.
render {
...
return(
<div className = "container">
{element}
</div>
);
}
Пожалуйста, дайте мне знать, если это вообще возможно и как. Единственное возможное решение, которое я мог придумать, это, возможно, сохранить дочерние элементы в виде строк и использовать опасно SetInnerHTML для их генерации, но я действительно хочу уйти от использования опасно SetInnerHTML, особенно в таком виде.
Не уверен насчет синтаксического анализа, но когда вы хотите отобразить строку как необработанную HTML в реакции, единственный доступный для этого API — опасноSetInnerHTML
Посмотрите пример реакция-гиперскрипт в документации. Вы можете использовать библиотеку, если хотите, или просто реализовать ее с нуля, используя ту же идею, поскольку вы уже смогли поместить их в узлы DOM.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


В итоге я сделал то, чего не хотел, а именно опасно SetInnerHTML. Если кто-то предложит лучшее решение, пожалуйста, поделитесь им.
async getArticleComponents(data: any) {
if (!data)
return null;
let slides = []
let node = document.createRange().createContextualFragment(data).firstChild;
let children = node.childNodes;
for (let i = 0; i < children.length; i++) {
var element = (children[i] as HTMLDivElement);
var controlElement = element.attributes.getNamedItem("data-sp-controldata");
var jObj = controlElement ? JSON.parse(controlElement.value) : null;
if (jObj.controlType === 3) {
var childEle = element.firstElementChild;
var webPartData = childEle.attributes.getNamedItem("data-sp-webpartdata");
var wpJObj = webPartData ? JSON.parse(webPartData.value) : null;
if (wpJObj.title == "File viewer") {
let ext = (/.*\.(.*)/i).exec(wpJObj.properties.file)[1].toLowerCase();
if (ext === "pdf") {
var pdf = await fetch(`/api/SharePoint/GetFile?url=${encodeURIComponent(`${wpJObj.serverProcessedContent.links.serverRelativeUrl}`)}`)
.then(res => res.text())
.then(pdf => pdf ? `data:application/pdf;base64,${pdf}` : null);
slides.push(<PDFViewer key = {jObj.id} file = {{ pdf, fileName: "test" } as IPdfMeta} />);
}
} else
slides.push(<div key = {jObj.id} dangerouslySetInnerHTML = {{ __html: element.outerHTML }}></div>);
}
else if (jObj.controlType !== 0) {
slides.push(<div key = {jObj.id} dangerouslySetInnerHTML = {{ __html: element.outerHTML }}></div>);
}
}
return slides;
}
Вы можете попробовать реагировать-html-парсер.
Вы можете попробовать использовать
react-html-parsernpmjs.com/package/react-html-парсер для преобразования HTML в компонент React, а затем использовать его для своих целей.