Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes bug where Astro can't distinguish between two equal components… #846

Conversation

matsdahlin
Copy link
Contributor

@matsdahlin matsdahlin commented Jul 24, 2021

Changes

Includes a components props as distinguishing factor when generating hash for astroId, closes #844

Testing

Tested manually with example project. Would like help creating a unit test, but I can't get any Astro tests to run on my computer.

Docs

Bug fix only, no change needed in docs.

@changeset-bot
Copy link

changeset-bot bot commented Jul 24, 2021

🦋 Changeset detected

Latest commit: 2d728a0

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
astro Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link

vercel bot commented Jul 24, 2021

This pull request is being automatically deployed with Vercel (learn more).
To see the status of your deployments, click below or on the icon next to each commit.

astro-www – ./www

🔍 Inspect: https://vercel.com/pikapkg/astro-www/9yMQ68zmMkABAghrDMGGtgVu6UXc
✅ Preview: https://astro-www-git-fork-matsdahlin-bugfix-astroid-for-ed4ff4-pikapkg.vercel.app

astro-docs – ./docs

🔍 Inspect: https://vercel.com/pikapkg/astro-docs/5G6Sf8XqtreF3Y48S4pedS2vvJiR
✅ Preview: https://astro-docs-git-fork-matsdahlin-bugfix-astroid-fo-28552b-pikapkg.vercel.app

@@ -187,7 +187,8 @@ export function __astro_component(Component: any, metadata: AstroComponentMetada
}

// If we ARE hydrating this component, let's generate the hydration script
const astroId = hash.unique(html);
const stringifiedProps = JSON.stringify(props);
const astroId = hash.unique(html + stringifiedProps);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happens if two components with the same props? It sounds like we end up with two astro-root components with the same uid attribute.

Curious if this is something that we should optimize for (just render all matching components with the same hydrate script) or be super explicit about (each component gets a completely unique id, not based on html).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should get rid of these inline scripts altogether imo and colocate everything in the head. A small inlined custom element would make these a lot easier.

But I think we should merge this fix in first because this seems like a bad bug to me.

Copy link
Contributor Author

@matsdahlin matsdahlin Jul 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happens if two components with the same props? It sounds like we end up with two astro-root components with the same uid attribute.

Curious if this is something that we should optimize for (just render all matching components with the same hydrate script) or be super explicit about (each component gets a completely unique id, not based on html).

My opinion is that the way it currently works goes against established patterns of hydration, and it's not the expected behavior.

Using a modified version of the React counter component as an example:

import React, { useState } from 'react';

export default function Counter({ initialValue, children }) {
  const [count, setCount] = useState(initialValue);
  const add = () => setCount((i) => i + 1);
  const subtract = () => setCount((i) => i - 1);

  return (
    <>
      <div className="counter">
        <button onClick={subtract}>-</button>
        <pre>{count}</pre>
        <button onClick={add}>+</button>
      </div>
      <div className="children">{children}</div>
    </>
  );
}

And then use two instances with different initial values in an Astro file:

<Counter initialValue={0} client:idle />
<Counter initialValue={10} client:idle />

The above code would result in both Counter components being hydrated with the same initialValue.

I believe that using the components props as part of the hash generation gives us both the current optimization (identical components with identical props will get the same hydrate script) and generates unique hydrate script when components differ only in what prop values get set from Astro.

Copy link
Contributor

@jasikpark jasikpark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me as a fix even if there are questions about whether the overarching API provided needs reworking!

@matthewp
Copy link
Contributor

Going to merge, let's work to improve how we do hydration in another issue (maybe an RFC for an overhaul).

@matthewp matthewp merged commit e89a99f into withastro:main Jul 27, 2021
@matsdahlin matsdahlin deleted the bugfix/astroid-for-hydration-script-ignores-prop-differences branch July 27, 2021 20:19
hlynursmari1 added a commit to hlynursmari1/astro that referenced this pull request Mar 17, 2022
Re-resolves an issue initially patched in withastro#846 but seemingly lost in the 0.21.0 mega-merge (withastro@d84bfe7).
This change makes the component render step account for all props, even if they don't affect the generated HTML, when deduplicating island mount.
matthewp pushed a commit that referenced this pull request Mar 18, 2022
* Fix island deduplication ignoring props.

Re-resolves an issue initially patched in #846 but seemingly lost in the 0.21.0 mega-merge (d84bfe7).
This change makes the component render step account for all props, even if they don't affect the generated HTML, when deduplicating island mount.

* Fix React component test using different rendered props to test deduplication.

* fix: improve serialization support for non-JSON objects

Co-authored-by: Nate Moore <[email protected]>
@github-actions github-actions bot mentioned this pull request Mar 18, 2022
@github-actions github-actions bot mentioned this pull request Mar 25, 2022
SiriousHunter pushed a commit to SiriousHunter/astro that referenced this pull request Feb 3, 2023
SiriousHunter pushed a commit to SiriousHunter/astro that referenced this pull request Feb 3, 2023
* Fix island deduplication ignoring props.

Re-resolves an issue initially patched in withastro#846 but seemingly lost in the 0.21.0 mega-merge (withastro@d84bfe7).
This change makes the component render step account for all props, even if they don't affect the generated HTML, when deduplicating island mount.

* Fix React component test using different rendered props to test deduplication.

* fix: improve serialization support for non-JSON objects

Co-authored-by: Nate Moore <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants