Summary
<Graphistry> declares its defaults via Graphistry.defaultProps. React 19 no longer applies defaultProps to function components, so under React 19 every prop the consumer omits arrives as undefined — and several of those are serialized directly into the iframe URL.
The most damaging one is play. A consumer that simply does not pass play gets play=0, which freezes the initial force layout. On a large graph (~25k nodes / 200k edges) the result is an unusable static bubble.
Reproduced against React 19.2 with @graphistry/client-api-react@4.6.6. Still present in the current 5.1.8 — I unpacked the published tarball to confirm before filing.
Mechanism
// v4.6.6 dist/index.cjs.js:8800 / v5.1.8 dist/index.cjs.js:9203
var defaultProps = { ..., play: 5, showInfo: true, showMenu: true, allowFullScreen: true, ... };
// v4.6.6 dist/index.cjs.js:9200 / v5.1.8 dist/index.cjs.js:9600
const playNormalized = typeof play === "boolean" ? play : (play | 0) * 1e3;
// v4.6.6 dist/index.cjs.js:9202 / v5.1.8 dist/index.cjs.js:9608
const url = `${graphistryHost || ""}/graph/graph.html?play=${playNormalized}&info=${showInfo}&splashAfter=${showSplashScreen}&dataset=...`;
// v4.6.6 dist/index.cjs.js:9264 / v5.1.8 dist/index.cjs.js:9665
Graphistry.defaultProps = defaultProps; // <- ignored by React 19
Under React 19, play === undefined, so undefined | 0 → 0 → play=0.
Likewise showInfo === undefined template-interpolates to the literal string, producing info=undefined in the query string.
Observed vs expected URL
Consumer renders <Graphistry dataset={id} graphistryHost={host} /> with no play and no showInfo.
Under React 18:
https://hub.graphistry.com/graph/graph.html?play=5000&info=true&splashAfter=false&dataset=<id>
Under React 19:
https://hub.graphistry.com/graph/graph.html?play=0&info=undefined&splashAfter=false&dataset=<id>
Other props silently lost the same way
Anything in defaultProps is affected, but these change behavior rather than just cosmetics:
allowFullScreen: true → undefined → the iframe is rendered with allowFullScreen={false}.
tolerateLoadErrors: true → falsy, changing iframe load-error handling.
iframeClassName: "graphistry-iframe" → the iframe loses the class consumers may style against.
showMenu / showToolbar / showLoadingIndicator / loadingMessage → the loading placeholder renders without its header/message.
Suggested fix
Replace Graphistry.defaultProps with parameter defaults (or nullish coalescing) inside the component, which works across React 16–19:
const Graphistry = React.forwardRef(({
play = 5,
showInfo = true,
showMenu = true,
allowFullScreen = true,
tolerateLoadErrors = true,
iframeClassName = "graphistry-iframe",
...rest
}, ref) => { ... });
Defensively, playNormalized could also guard the coercion so a missing value can never masquerade as an explicit 0:
const playNormalized = typeof play === "boolean" ? play : (Number.isFinite(play) ? play : 5) * 1000;
That distinction matters because play=0 is a legitimate, intentional setting for precomputed / radial / UMAP layouts — so consumers cannot tell "frozen on purpose" from "frozen because a default went missing".
propTypes on function components is likewise deprecated and dropped in React 19, so it may be worth removing in the same pass.
Downstream
Reported in Louie: https://github.com/graphistry/graphistrygpt/issues/3898
Louie-side workaround (restores the dropped defaults at the call site): https://github.com/graphistry/graphistrygpt/pull/3899
We are pinning ^4.6.6 and compensating locally for now. Happy to send a PR here if the parameter-defaults approach looks right to you.
Summary
<Graphistry>declares its defaults viaGraphistry.defaultProps. React 19 no longer appliesdefaultPropsto function components, so under React 19 every prop the consumer omits arrives asundefined— and several of those are serialized directly into the iframe URL.The most damaging one is
play. A consumer that simply does not passplaygetsplay=0, which freezes the initial force layout. On a large graph (~25k nodes / 200k edges) the result is an unusable static bubble.Reproduced against React 19.2 with
@graphistry/client-api-react@4.6.6. Still present in the current5.1.8— I unpacked the published tarball to confirm before filing.Mechanism
Under React 19,
play === undefined, soundefined | 0→0→play=0.Likewise
showInfo === undefinedtemplate-interpolates to the literal string, producinginfo=undefinedin the query string.Observed vs expected URL
Consumer renders
<Graphistry dataset={id} graphistryHost={host} />with noplayand noshowInfo.Under React 18:
Under React 19:
Other props silently lost the same way
Anything in
defaultPropsis affected, but these change behavior rather than just cosmetics:allowFullScreen: true→undefined→ the iframe is rendered withallowFullScreen={false}.tolerateLoadErrors: true→ falsy, changing iframe load-error handling.iframeClassName: "graphistry-iframe"→ the iframe loses the class consumers may style against.showMenu/showToolbar/showLoadingIndicator/loadingMessage→ the loading placeholder renders without its header/message.Suggested fix
Replace
Graphistry.defaultPropswith parameter defaults (or nullish coalescing) inside the component, which works across React 16–19:Defensively,
playNormalizedcould also guard the coercion so a missing value can never masquerade as an explicit0:That distinction matters because
play=0is a legitimate, intentional setting for precomputed / radial / UMAP layouts — so consumers cannot tell "frozen on purpose" from "frozen because a default went missing".propTypeson function components is likewise deprecated and dropped in React 19, so it may be worth removing in the same pass.Downstream
Reported in Louie: https://github.com/graphistry/graphistrygpt/issues/3898
Louie-side workaround (restores the dropped defaults at the call site): https://github.com/graphistry/graphistrygpt/pull/3899
We are pinning
^4.6.6and compensating locally for now. Happy to send a PR here if the parameter-defaults approach looks right to you.