Могу ли я создать элемент React из строки HTML или узла/элемента dom

Я получаю строку 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, особенно в таком виде.

Вы можете попробовать использовать react-html-parsernpmjs.com/package/react-html-парсер для преобразования HTML в компонент React, а затем использовать его для своих целей.

Rikin 06.06.2019 22:43

Не уверен насчет синтаксического анализа, но когда вы хотите отобразить строку как необработанную HTML в реакции, единственный доступный для этого API — опасноSetInnerHTML

Sagiv b.g 06.06.2019 22:48

Посмотрите пример реакция-гиперскрипт в документации. Вы можете использовать библиотеку, если хотите, или просто реализовать ее с нуля, используя ту же идею, поскольку вы уже смогли поместить их в узлы DOM.

marsheth 07.06.2019 01:45
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
3
5 456
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

В итоге я сделал то, чего не хотел, а именно опасно 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-парсер.

Другие вопросы по теме