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

Auto generate IDs (for <defs>) during render, with SSR support #1

Merged
merged 13 commits into from
Feb 5, 2020

Conversation

exogen
Copy link
Owner

@exogen exogen commented Feb 4, 2020

One common complaint is that rendering the same SVG multiple times results in duplicate IDs on the page. See airbnb#57.

IDs are pretty much necessary for using things like gradients. The problem is since the SVG is rendered inline, and sometimes the same SVG is rendered multiple times, the IDs are duplicated on the page. This is not only invalid, but results in actual bugs.

For example, let's say one of the SVGs becomes hidden:

<div style="display: none">
  <svg>...</svg>
</div>

<svg>...</svg>

Did you know hiding the elements that url(#foo) references in an SVG cause their referents to also hide (in some browsers at least)? Yeah, weird. Even though the ID'd elements are still in the DOM, hiding them causes their reference to hide also.

In our case, we are rendering country flag icons both in a dropdown and in a footer. When the dropdown is hidden, so are all the flags in the footer.

This patch adds runtime code similar to Reach UI's Auto ID. NOTE THAT THIS MEANS YOU'LL NEED TO CHANGE babel-plugin-inline-react-svg TO BE IN dependencies, NOT devDependencies. All IDs are replaced with references to the (newly built-in) useId() hook. This ensures that you can render the same SVG as many times as you like, and each instance will have unique IDs.

If using server-side rendering (SSR), you can wrap your app in the <AutoIdProvider> that's also exported, which will ensure that the IDs match up during hydration.

import { AutoIdProvider } from 'babel-plugin-inline-react-svg/auto-id';

Would using <use> and/or shared non-hidden <defs> be technically better?

Yes, but extremely complicated. This requires a central manager and portals, which are both quite difficult for SSR (we'd need some specialized helper like react-helmet or next/head, except for stuff in <body> instead of <head>).

Fixes airbnb#57.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
1 participant