Estoy usando Datawrapper para mostrar gráficos como iframes en mi sitio web.
Recientemente migré de Remark a MDX. Con la nueva configuración, mis gráficos de Datawrapper no se cargan antes de que la página que contiene los gráficos pueda cargarse en el sentido "tradicional" (es decir, presionar Actualizar o seguir la página que contiene los gráficos directamente).
Entonces, si sigue este enlace, los gráficos se muestran bien: kolstadmagnus.no/ekspert-mener-a-ha-svaret-bak-krfs-stortingssmell .
Pero si va a la página de inicio ( kolstadmagnus.no ) y luego presiona el enlace (segunda publicación superior), los gráficos no se mostrarán.
Los iframes de Datawrapper usan este script para que los iframes respondan:
!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}();Dado que Gatsby funciona de la forma en que lo hace (sin cargar todas las páginas "tradicionalmente"; lo siento, no sé cómo se llama la característica), tuve que poner este script en el archivo html.js, así:
<body {...props.bodyAttributes}> {props.preBodyComponents} <div key={`body`} id="___gatsby" dangerouslySetInnerHTML={{ __html: props.body }} /> {props.postBodyComponents} <script dangerouslySetInnerHTML={{ __html: ` !function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}(); ` }} /> </body>;Esto hace que la secuencia de comandos se ejecute para todo el sitio web en lugar de solo para esa página, resolviendo así el problema en el que se requiere actualizar después de ingresar a las páginas con los iframes.
Sin embargo, con MDX, los problemas han vuelto. Pero ahora los iframes no se muestran en absoluto.
¿Cómo puedo solucionar esto?
Gatsby extiende su navegación y su "página de carga" desde @reach/router , por lo tanto, desde React.
Desaconsejaría encarecidamente incrustar un script personalizado que deba representarse en ciertas páginas en html.js ya que, como señaló, se cargará globalmente. Puede lograr el mismo efecto ejecutándolo localmente o atomizándolo.
El problema al que te enfrentas es que el script apunta directamente al DOM (debido al uso de window.addEventListener ) mientras que en React (y por lo tanto con Gatsby) creas y manipulas un DOM virtual (vDOM). Jugar y manipular ambos puede causar comportamientos engañosos porque uno no sabe cuándo cambia el otro y viceversa, interrumpiendo el proceso de hidratación y rehidratación (es por eso que ves los resultados en la actualización: porque la hidratación nunca ocurre).
Dicho esto, la solución ideal sería usar un módulo Datawrapper basado en React como react-datawrapper-chart o usar otra solución personalizada. Hacer que los scripts respondan no es gran cosa, puede hacer los mismos cálculos usando código basado en React.
Alternativamente, siguiendo su enfoque de "trabajo", puede cargar su secuencia de comandos personalizada utilizando el componente Helmet en una página determinada:
const SomeSpecificPage = () =>{ return <> <Helmet> <script dangerouslySetInnerHTML={{ __html: ` !function(){"use strict";window.addEventListener("message", (function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}(); ` }} /> </Helmet> </> }