如何使用gatsby使脚本首次使用特殊组件? [英] How to make a script working the first time for a special component with gatsby?
问题描述
我正在使用Gatsby从事静态网站项目.我有几个markdown页面,只有一个通过cdn调用使用脚本.我不需要在网站上的任何地方调用脚本,而只想在需要更新<head>
时调用和使用脚本.这就是为什么我开始在头盔组件中使用逻辑的原因.
实际版本(每页调用一次):
return(
<Layout>
<Seo />
<Helmet>
<script src="myScriptForOnePage.js" />
</Helmet>
....
</Layout>
);
例外版本:
return(
<Layout>
<Seo />
{ ifIHaveToRenderMyPage ? (
<Helmet>
<script src="myScriptForOnePage.js" />
</Helmet>
):null}
....
</Layout>
);
这很好.我的脚本仅在需要时加载. 但是,在加载特殊页面时不会第一次执行...我需要在页面上浏览两次以查看加载的脚本是否正常工作.
这是该问题的例证.例如,在这个项目中,我想添加一个传单地图.因此,myScriptForOnePage.js
等于https://unpkg.com/leaflet@1.6.0/dist/leaflet.js
(加上CSS文件).
当我第一次加载页面时:
如您所见,L is not defined
.即使脚本在network语句中也不会执行.当我返回菜单时,再次单击传单(无需重新加载):
可以随时显示地图.
我在生活中缺少某些东西吗?我该如何解决?
由于Gatsby和您的问题是异步的,因此当出现以下情况时,您需要使用state
重新呈现DOM并添加新的组件(<Helmet>
)您的ifIHaveToRenderMyPage
已设置.试试:
import React, { useEffect, useState } from 'react';
import { Helmet } from 'react-helmet';
const yourComponent = () => {
const [myScript, setMyScript] = useState([]);
useEffect(() => {
let myScriptForOnePage= <Helmet>
<script src="myScriptForOnePage.js" />
</Helmet>;
setMyScript(myScriptForOnePage);
},[]);
return(
<Layout>
<Seo />
{ifIHaveToRenderMyPage && myScript}
....
</Layout>
);
因此,基本上,我使用一个useState
钩子,该钩子最初设置为一个空数组(必须是一个要填充组件的空数组),并且我已经使用useEffect
钩子创建了一个效果,该效果会在组件和组件生成DOM树(如果需要,可以使用ifIHaveToRenderMyPage
作为依赖项).
此外,我已经更改了三元条件,因为您不需要返回null
值,只需使用&&
比较器检查ifIHaveToRenderMyPage
是否为true
,它就会更干净,更高效.>
在我的本地计算机中,使用build
命令并首先进行渲染:
有了新的更新,您是否尝试过从传单中导入L?如官方文档所示:
import React from 'react'
import { render } from 'react-dom'
import { Map, Marker, Popup, TileLayer } from 'react-leaflet'
const position = [51.505, -0.09]
const map = (
<Map center={position} zoom={13}>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution="© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors"
/>
<Marker position={position}>
<Popup>A pretty CSS3 popup.<br />Easily customizable.</Popup>
</Marker>
</Map>
)
render(map, document.getElementById('map-container'))
I am working on a static website project using Gatsby. I have several markdown pages, and only one is using a script through a cdn call. Instead of calling my script wherever i am on the website, I only to want to call and use my script when I need to update my <head>
. That's why I started to use logical inside my Helmet component.
Actual version (calling on every pages):
return(
<Layout>
<Seo />
<Helmet>
<script src="myScriptForOnePage.js" />
</Helmet>
....
</Layout>
);
Excepted version:
return(
<Layout>
<Seo />
{ ifIHaveToRenderMyPage ? (
<Helmet>
<script src="myScriptForOnePage.js" />
</Helmet>
):null}
....
</Layout>
);
This works fine. My script is only loaded when I need it. However, It is not executed the first time when I load my special page... I need to go twice on my page to see my loaded script working.
This is an illustration of the issue. For example, in this project, I want to add a leaflet map. So, myScriptForOnePage.js
equals to https://unpkg.com/leaflet@1.6.0/dist/leaflet.js
(plus css file).
When I first load the page:
As you might see, L is not defined
. My script is not executed even if it is present in the network statement. When I go back on the menu, and click again on leaflet post (without reloading):
The map is ready to be displayed.
Am I missing something in the life component? How can I fix this?
Due to the asynchronously of Gatsby and your issue, you need to use an state
to rerender the DOM and add a new component (<Helmet>
) when your ifIHaveToRenderMyPage
is set. Try:
import React, { useEffect, useState } from 'react';
import { Helmet } from 'react-helmet';
const yourComponent = () => {
const [myScript, setMyScript] = useState([]);
useEffect(() => {
let myScriptForOnePage= <Helmet>
<script src="myScriptForOnePage.js" />
</Helmet>;
setMyScript(myScriptForOnePage);
},[]);
return(
<Layout>
<Seo />
{ifIHaveToRenderMyPage && myScript}
....
</Layout>
);
So, basically I use a useState
hook initially set as an empty array (must be an empty array to be filled with a component) and I've created an effect using useEffect
hook that triggers when the component and DOM tree is generated (you can use ifIHaveToRenderMyPage
as a dependency if you want by [ifIHaveToRenderMyPage]
).
In addition, I've changed the ternary condition because you don't need to return a null
value, just check if ifIHaveToRenderMyPage
is true
using &&
comparator, it's cleaner and efficient.
In my local machine with a build
command and first rendering:
With the new updates, have you tried importing L from leaflet? As the official documentation shows:
import React from 'react'
import { render } from 'react-dom'
import { Map, Marker, Popup, TileLayer } from 'react-leaflet'
const position = [51.505, -0.09]
const map = (
<Map center={position} zoom={13}>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution="© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors"
/>
<Marker position={position}>
<Popup>A pretty CSS3 popup.<br />Easily customizable.</Popup>
</Marker>
</Map>
)
render(map, document.getElementById('map-container'))
这篇关于如何使用gatsby使脚本首次使用特殊组件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!