Este în regulă să folosiți ReactDOMServer.renderToString în browser în zonele în care React nu gestionează direct DOM? (Programare, Reactjs, Leaflet, React Dom)

Shane Cavaliere a intrebat.

Lucrez la o aplicație care utilizează Leaflet (prin intermediul react-leaflet). Leaflet manipulează direct DOM. Biblioteca react-leaflet nu schimbă acest lucru, ci doar vă oferă componente React pe care le puteți utiliza pentru a controla harta Leaflet într-un mod compatibil cu React.

În această aplicație, vreau să folosesc markeri de hartă personalizați care sunt div-uri care conțin câteva elemente simple. Modul de a face acest lucru în Leaflet este să setați markerul dvs. icon la o proprietate DivIcon, , în care vă puteți seta HTML-ul personalizat. Setați acel HTML intern prin setarea proprietății DivIcon’s html la un șir de caractere care conține HTML. În cazul meu, vreau ca acel HTML să fie redat de o componentă React.

Pentru a face acest lucru, se pare că abordarea corectă este de a utiliza ReactDOMServer.renderToString() pentru a reda componenta pe care o doresc în interiorul markerului de hartă într-un șir de caractere, pe care îl voi seta apoi ca proprietate html din DivIcon:

MyMarker.js:

import React, { Component } from 'react'
import { renderToString } from 'react-dom/server'
import { Marker } from 'react-leaflet'
import { divIcon } from 'leaflet'

import MarkerContents from './MarkerContents'

export class MyMarker extends Component {
  render() {
    const markerContents = renderToString(<MarkerContents data={this.props.data} />)
    const myDivIcon = divIcon({
      className: 'my-marker',
      html: markerContents
    })

    return (
      <Marker
        position={this.props.position}
        icon={myDivIcon} />
    )
  }
}

Cu toate acestea, în conformitate cu React docs:

Acest [renderToString] ar trebui să fie utilizat numai pe server.

Este aceasta o regulă strictă, sau este menită doar să descurajeze oamenii să ocolească gestionarea eficientă a DOM de către ReactDOM?

Nu mă pot gândi la o altă modalitate (mai bună) de a realiza ceea ce urmăresc. Orice comentarii sau idei ar fi foarte apreciate.

Comentarii

  • Nu sunt sigur dacă acest lucru va ajuta, dar: facebook.github.io/react/tips/dangerously-set-inner-html.html și stackoverflow.com/questions/21285262/…  > Por lux.
  • Mulțumesc, dar de fapt nu încerc să setez manual innerHTML nicăieri. Vreau doar să pregătesc un șir HTML din componentele React pe care să îl pot folosi într-un Leaflet DivIcon și mă întreb dacă există vreun motiv întemeiat pentru a nu folosi ReactDOMServer.renderToString() pentru a realiza acest lucru. Cu siguranță un bun memento pentru a fi diligent cu privire la igienizarea HTML, totuși. –  > Por Shane Cavaliere.
  • Da, presupun că este opusul polar, nu? Singurul mod în care am reușit să extrag HTML-ul pur dintr-o redare este prin următoarele: codepen.io/mikechabot/pen/xVMwgN?editors=0011 După cum puteți vedea, putem să descărcăm "<div data-reactid='.0'>Hello, World.</div>" în consolă prin refs, , care este componenta noastră, dar pentru a face acest lucru a trebuit să ne conectăm la DOM. Aș încerca să găsesc un dezvoltator React pe Twitter și să le pun această problemă direct, altfel, de ce să nu încercăm? renderToString(), , adică. –  > Por lux.
  • @imjared Da, am sfârșit prin a folosi ReactDOMServer.renderToString() și a funcționat bine. Nu am observat nicio problemă până acum. –  > Por Shane Cavaliere.
  • Înțelegerea mea este că ReactDOM.renderToStaticMarkup este cel mai potrivit pentru elemente statice și că atributele DOM suplimentare adăugate de către ReactDOMServer.renderToString sunt utile pentru manipularea DOM internă a lui React atunci când se redau. Dacă nu mă înșel, cea mai bună variantă de utilizat depinde probabil de faptul dacă anticipezi că vor avea loc actualizări pe acea componentă în viitor. –  > Por Shane Cavaliere.
3 răspunsuri
Thomas Grainger

Conform noii documentații: https://reactjs.org/docs/react-dom-server.html

Următoarele metode pot fi utilizate atât în mediul server, cât și în mediul browser:

  • renderToString()
  • renderToStaticMarkup()

Mohamed Shaaban

Știu că este o întrebare prea veche, dar din moment ce nu a primit răspuns, am vrut să împărtășesc gândurile mele.

Am folosit același lucru, renderToString, , dar cum documentația recomandă să nu-l folosim pe partea de client, am realizat acest lucru în alt mod, folosind metoda react-dom‘s render pentru a reda componenta personalizată în div

var myDiv = document.createElement('div');

ReactDOM.render(
  <MarkerContents data={this.props.data} />,
  myDiv
);

var myIcon = L.divIcon({ 
    iconSize: new L.Point(50, 50), 
    html: myDiv.innerHTML
});

Comentarii

  • Așa făceam până când React 16 a început să facă randare async. Al 3-lea parametru al render trebuie să fie o funcție de callback înainte de a citi innerHTML-ul, astfel: ReactDOM.render(component, myDiv, () => console.log(myDiv.innerHTML)) –  > Por styfle.
  • Am folosit-o și acum nu sunt chemați gestionarii mei de evenimente. Prin redarea componentei în obiect js, mai degrabă decât în dom. perturbăm legarea evenimentelor pentru componenta markerContent? –  > Por Rehan Umar.
Christian Fritz

După cum a spus deja Thomas, da, puteți utiliza renderToString pe client. Totuși, pentru a fi clar, va trebui să importați ReactDOMServer pe client, ceea ce poate părea contra-intuitiv, dar pare a fi corect. Exemplu (pe client):

import React from 'react';
import ReactDOMServer from 'react-dom/server';

const MyComp = (props) => {
  const html = ReactDOMServer.renderToString(<div>{someFunc(props)}</div>);
  // do something with your html, then
  return <div dangerouslySetInnerHTML={{__html: html}}></div>;
};