Skip to content

Add auto-init/auto-cleanup support so consumers need minimal integration code #166

Description

@coderabbitai

Summary

Consumers of SocialShareButton (e.g., StabilityNexus/Chainvoice) currently have to write custom lifecycle glue code around the library because the CDN script only attaches the SocialShareButton class to window and does not auto-mount, auto-cleanup, or auto-update itself. Today's consumer code must:

  • Poll for window.SocialShareButton to exist (since script/DOM load order is not guaranteed).
  • Manually call new window.SocialShareButton({ container: '#id' }) to render the button.
  • Track whether it's already initialized to avoid duplicate buttons on re-render/remount.
  • Manually call .destroy() on unmount to avoid leftover/duplicate instances.
  • Manually call .updateOptions({ url, title }) on every route change, since url/title are captured once at construction time and never recomputed automatically.

This defeats the goal of the library: providing a minimal-code drop-in share button for client applications, especially SPAs using client-side routing (e.g., React Router) where native popstate does not fire on pushState.

Proposed change

Add an opt-in auto-init routine to social-share-button.js that:

  1. Scans the DOM for elements marked with a data-social-share attribute (or similar convention) on script load (DOMContentLoaded or immediately if already loaded), and instantiates SocialShareButton for each, using data-url / data-title attributes (falling back to window.location.href / document.title).
  2. Guards against duplicate initialization per element (e.g., store the instance on the element itself).
  3. Listens for popstate and hashchange to call updateOptions({ url, title }) automatically. For SPA frameworks that use history.pushState without dispatching popstate, consider patching history.pushState/replaceState or documenting a small manual "notify" API consumers can call.
  4. Cleans up automatically when the container is removed from the DOM (e.g., via a MutationObserver calling .destroy()), so SPA route unmounts don't leak instances.

Rationale

Discussed in StabilityNexus/Chainvoice PR #182, where the integration currently requires ~40 lines of useEffect-based polling/init/destroy/updateOptions glue in frontend/src/components/Navbar.jsx just to use the library correctly. This is the opposite of the library's stated goal of minimal client-side integration.

Affected areas

  • src/social-share-button.js (constructor/auto-init logic, currently only assigns window.SocialShareButton = SocialShareButton at the bottom with no auto-init hook)
  • Documentation / README (usage instructions should show the new minimal data-social-share attribute usage, and clarify SPA route-change behavior)

Acceptance criteria

  • A consumer can add <div data-social-share></div> to any page/component with only the CDN <script>/<link> tags, no additional JS required, and the button renders correctly.
  • The share button reflects the current page URL/title without any consumer-side polling, initialization, or cleanup code.
  • On SPA route changes (React Router or similar), the shared URL/title updates without consumer code (native popstate/hashchange, or a documented lightweight hook for pushState-based routers).
  • Removing the container element from the DOM (e.g., component unmount in a SPA) does not leak duplicate button instances if the element is re-added later.
  • No duplicate buttons are created if the auto-init logic runs more than once (e.g., React Strict Mode double-invoking effects, or the script being re-evaluated).

Steps to verify

  1. Include only the CDN <script> and <link> tags plus <div data-social-share></div> in a test HTML page — verify the share button renders without any extra JS.
  2. Click the share button and confirm the shared URL/title match the current page.
  3. In a SPA test harness (e.g., a small React Router app), navigate between routes and confirm the share button's URL/title update automatically, with no consumer glue code.
  4. Mount/unmount the container element repeatedly and confirm no duplicate buttons or memory leaks (e.g., check via DOM inspection or a leak-detection script).
  5. Verify existing manual usage (new SocialShareButton({ container: ... })) continues to work unchanged for backward compatibility.

References

Requested by: @kpj2006

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions