无法根据生产中 Gatsby 应用 运行 中的 URL 参数更新 JSX 属性
Unable to update JSX attribute based on URL parameter in a Gatsby app running in production
在生产模式下,URL 参数值不能用于呈现动态属性值。相同的 URL 参数值可用于呈现特定组件。
我已经建立了一个包含最少可重现示例的 repo。
https://github.com/mikepuglisi/gatsby-dynamic-attribute-bug
我们已经能够通过将参数值存储在状态中来解决这个问题,但我不明白为什么这是必要的(特别是因为它呈现了正确的 div)。
相关代码(src/pages/index.js)
const IndexPage = ({location}) => {
const params = new URLSearchParams(location.search);
const color = params.get('color');
return (
<Layout>
<SEO title="Home" />
<h1>Hi people</h1>
{ color ?
<p style={{color: color}}>
I SHOULD BE THE COLOR {color} in production mode even after hitting CTRL+F5 (hard refresh)
</p> :
<p>
No Color was passed. Add ?color=blue to URL and hit CTRL+F5 to ensure a hard refresh
</p>
}
<div style={{ maxWidth: `300px`, marginBottom: `1.45rem` }}>
<Image />
</div>
<Link to="/page-2/">Go to page 2</Link>
</Layout>
)
}
url 参数 ?color=blue
应该能够呈现适当的 div 并呈现适当的样式。 div 显示正确,但正确的样式显示不正确。Issue Screenshot
这个问题似乎是 hydration
进程如何为服务器呈现的 React 应用程序工作。
简答
您需要为颜色设置初始状态,然后在 useEffect
挂钩中更新它:
const IndexPage = ({location}) => {
const [color, setColor] = useState();
useEffect(() => {
setColor(new URLSearchParams(location.search).get('color'));
}, location)
return (
<Layout>
<SEO title="Home" />
<h1>Hi people</h1>
{ color ?
<p style={{color: color}}>
I SHOULD BE THE COLOR {color} in production mode even after hitting CTRL+F5 (hard referesh)
</p> :
<p>
No Color was passed. Add ?color=blue to URL and hit CTRL+F5 to ensure a hard refresh
</p>
}
<div style={{ maxWidth: `300px`, marginBottom: `1.45rem` }}>
<Image />
</div>
<Link to="/page-2/">Go to page 2</Link>
</Layout>
)
}
长答案
在构建用于生产的 Gatsby 应用程序时,它会为使用 ReactDOMSever
. When you first load a page in the browser, it firsts loads the static HTML and then it needs to boot up React and hydrate
您的应用程序的您呈现静态 HTML。
在对您的应用程序进行水化后,React 会期望您的 HTML 内容与 client-side 呈现的 React 应用程序的第一次呈现的内容相同。但是,在您的情况下,情况并非如此。
在您的 React 组件的第一次渲染中,您的段落元素上应该有一个 style
属性,其颜色值在 URL 查询参数中找到。为页面构建静态 HTML 时,您的段落元素上不会有 style
属性,因为服务器上不存在查询参数。
您可能想知道为什么文本内容会在初始呈现时正确呈现您的查询参数中的颜色值。这是因为 hydrate
方法可以修补文本内容中的差异,但它不能修补 HTML 属性中的差异,这就是段落元素上的 style
属性所发生的情况。
来自 hydrate
方法的 React 文档:
React expects that the rendered content is identical between the server and the client. It can patch up differences in text content, but you should treat mismatches as bugs and fix them. In development mode, React warns about mismatches during hydration. There are no guarantees that attribute differences will be patched up in case of mismatches. This is important for performance reasons because in most apps, mismatches are rare, and so validating all markup would be prohibitively expensive.
由于 "mismatch" 介于初始 HTML 内容之间,您应该改为将 color
的默认值设置为状态 属性,然后更新该值当组件首次安装时。这样,当您第一次在客户端加载应用程序并且存在 color
查询参数时,您将能够更新挂载状态以触发 React 组件的 re-render。
资源
在生产模式下,URL 参数值不能用于呈现动态属性值。相同的 URL 参数值可用于呈现特定组件。
我已经建立了一个包含最少可重现示例的 repo。
https://github.com/mikepuglisi/gatsby-dynamic-attribute-bug
我们已经能够通过将参数值存储在状态中来解决这个问题,但我不明白为什么这是必要的(特别是因为它呈现了正确的 div)。
相关代码(src/pages/index.js)
const IndexPage = ({location}) => {
const params = new URLSearchParams(location.search);
const color = params.get('color');
return (
<Layout>
<SEO title="Home" />
<h1>Hi people</h1>
{ color ?
<p style={{color: color}}>
I SHOULD BE THE COLOR {color} in production mode even after hitting CTRL+F5 (hard refresh)
</p> :
<p>
No Color was passed. Add ?color=blue to URL and hit CTRL+F5 to ensure a hard refresh
</p>
}
<div style={{ maxWidth: `300px`, marginBottom: `1.45rem` }}>
<Image />
</div>
<Link to="/page-2/">Go to page 2</Link>
</Layout>
)
}
url 参数 ?color=blue
应该能够呈现适当的 div 并呈现适当的样式。 div 显示正确,但正确的样式显示不正确。Issue Screenshot
这个问题似乎是 hydration
进程如何为服务器呈现的 React 应用程序工作。
简答
您需要为颜色设置初始状态,然后在 useEffect
挂钩中更新它:
const IndexPage = ({location}) => {
const [color, setColor] = useState();
useEffect(() => {
setColor(new URLSearchParams(location.search).get('color'));
}, location)
return (
<Layout>
<SEO title="Home" />
<h1>Hi people</h1>
{ color ?
<p style={{color: color}}>
I SHOULD BE THE COLOR {color} in production mode even after hitting CTRL+F5 (hard referesh)
</p> :
<p>
No Color was passed. Add ?color=blue to URL and hit CTRL+F5 to ensure a hard refresh
</p>
}
<div style={{ maxWidth: `300px`, marginBottom: `1.45rem` }}>
<Image />
</div>
<Link to="/page-2/">Go to page 2</Link>
</Layout>
)
}
长答案
在构建用于生产的 Gatsby 应用程序时,它会为使用 ReactDOMSever
. When you first load a page in the browser, it firsts loads the static HTML and then it needs to boot up React and hydrate
您的应用程序的您呈现静态 HTML。
在对您的应用程序进行水化后,React 会期望您的 HTML 内容与 client-side 呈现的 React 应用程序的第一次呈现的内容相同。但是,在您的情况下,情况并非如此。
在您的 React 组件的第一次渲染中,您的段落元素上应该有一个 style
属性,其颜色值在 URL 查询参数中找到。为页面构建静态 HTML 时,您的段落元素上不会有 style
属性,因为服务器上不存在查询参数。
您可能想知道为什么文本内容会在初始呈现时正确呈现您的查询参数中的颜色值。这是因为 hydrate
方法可以修补文本内容中的差异,但它不能修补 HTML 属性中的差异,这就是段落元素上的 style
属性所发生的情况。
来自 hydrate
方法的 React 文档:
React expects that the rendered content is identical between the server and the client. It can patch up differences in text content, but you should treat mismatches as bugs and fix them. In development mode, React warns about mismatches during hydration. There are no guarantees that attribute differences will be patched up in case of mismatches. This is important for performance reasons because in most apps, mismatches are rare, and so validating all markup would be prohibitively expensive.
由于 "mismatch" 介于初始 HTML 内容之间,您应该改为将 color
的默认值设置为状态 属性,然后更新该值当组件首次安装时。这样,当您第一次在客户端加载应用程序并且存在 color
查询参数时,您将能够更新挂载状态以触发 React 组件的 re-render。