Skip to content

How to prevent React from modifying elements manipulated by external code?  #10923

@giratikanon

Description

@giratikanon

The New York Times is rebuilding its website using React. Currently, it’s an isomorphic app that has both server- and client-side renders.

Our question: What's the best way to include a non-React interactive graphic — maps, charts and other visualizations created by custom code — within a fully React page?

Our ideal scenario:

  • Server-side React renders the initial HTML for a graphic, using dangerouslySetInnerHTML, as part of a React page
  • Client-side React never touches those elements again, even during component mounting

We thought React 16 might solve this with hydrate method, but it still removes nodes that it doesn't expect, such as nodes generated by D3 or other client-side code. None of the options in Integrating with Other Libraries seem to be an exact match either.

The classic use case is a graphic with a D3 map. The server-side HTML includes text and a placeholder

for the map, as well as the map JS. On page load, the map is immediately drawn by D3 but gets erased when React mounts client-side. The D3 nodes aren’t included in the server-side output, because they often vary based on viewport, device, etc.

Here’s a trivial example, showing React 16’s hydrate removing client-created nodes after one second. On mobile devices, loading the React library and potentially other dependencies could take some seconds.

The simplest solution I can think of is a shouldComponentMount function, where we could return false. The rest of the React components on the page would mount, but leave the interactive graphic part alone. There are probably other solutions.

Constraints:

  • We need to use dangerouslySetInnerHTML, because we need to deploy graphics outside of site releases
  • We need to render the initial HTML server-side for performance and simplicity
  • We can’t use iFrames for everything, as they’re not flexible enough
  • We can’t re-render or reattach elements, as that causes many problems — CSS animations restart, media playback is interrupted, input cursors and text selections are lost, etc.

Any guidance is appreciated.

cc @gaearon @leeb

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions