无法在生产环境中运行的Gatsby应用中基于URL参数更新JSX属性 [英] Unable to update JSX attribute based on URL parameter in a Gatsby app running in production

查看:138
本文介绍了无法在生产环境中运行的Gatsby应用中基于URL参数更新JSX属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在生产模式下,URL参数值不能用于呈现动态属性值.可以使用相同的URL参数值来呈现特定的组件.

In production mode, a URL parameter value can not be used to render dynamic attribute values. The same URL parameter value can be used to render a specific component.

我已经建立了一个带有最小可重复示例的仓库.

I have set up a repo with a minimum reproducible example.

https://github.com/mikepuglisi/gatsby-dynamic-attribute-bug

我们已经能够通过将参数值存储在状态中来解决此问题,但是我不明白为什么这是必要的(特别是因为它呈现了正确的div).

We've been able to work around this by storing the parameter values in state, but I don't see why that should be necessary (especially since it renders the correct div).

相关代码(src/pages/index.js)

Relevant Code (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显示正确,但样式不正确.问题屏幕截图

The url parameter ?color=blue should be able to render the appropriate div AND render the appropriate style. The div shows correctly, but the correct style does not.Issue Screenshot

推荐答案

这个问题似乎是hydration进程如何用于服务器渲染的React应用程序.

This problem seems to be how the hydration process works for server rendered React applications.

您需要设置颜色的初始状态,然后在useEffect挂钩中对其进行更新:

You need to set an initial state for the color and then update it in a useEffect hook:

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应用进行生产时,它会使用 .首次在浏览器中加载页面时,它首先加载静态HTML,然后需要启动React和 hydrate 您的应用.

Long Answer

When building your Gatsby app for production, it renders out static HTML for you using 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 your app.

在为您的应用程序充水后,React会期望您的HTML内容与客户端渲染的React应用程序的第一次渲染所呈现的内容相同.但是,就您而言,这是不正确的.

Upon hydrating your app, React will expect your HTML content to be identical to what would have been rendered on the first render of client-side rendered React application. However, in your case, this is not true.

在您的React组件的第一个渲染上,您的段落元素上应具有style属性,并具有在URL查询参数中找到的颜色值.为页面构建静态HTML时,您的段落元素将没有style属性,因为服务器上不存在查询参数.

On the first render for your React component, you should have a style attribute on your paragraph element with the value of the color found in the URL query params. When building the static HTML for the page, you will not have the style attribute on your paragraph element because query params don't exist on the server.

您可能想知道为什么文本内容在初始呈现时正确呈现了查询参数中的颜色值.这是因为 hydrate 方法可以修补文本内容中的差异,但是无法修补HTML属性中的差异,这就是段落元素上的style属性正在发生的情况.

You might be wondering why the text content correctly renders the color value from your query params on the initial render. This is because the hydrate method can patch differences in text content, but it cannot patch differences in your HTML attributes, which is what is happening with your style attribute on the paragraph element.

从React文档中获取hydrate方法:

From the React docs for the hydrate method:

React期望服务器和客户端之间呈现的内容相同. 它可以修补文本内容中的差异,但是您应将不匹配项视为错误并加以修复.在开发模式下,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.

由于初始HTML内容之间存在这种不匹配",因此您应该将color的默认值设置为state属性,然后在首次安装组件时更新该值.这样,当您第一次在客户端上加载应用程序并且存在一个color查询参数时,您将能够更新安装状态以触发您的React组件的重新渲染.

Because of this "mismatch" between the initial HTML content, you should instead set a default value for color as a state property, and then update that value when the component first mounts. That way, when you first load the app on the client and you have a color query param present, you will be able to update the state on mount to trigger a re-render of your React component.

  • Gatsby: Building the JavaScript App
  • ReactDOM hydrate() method

这篇关于无法在生产环境中运行的Gatsby应用中基于URL参数更新JSX属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆