Skip to content

Commit 0030755

Browse files
templates: runtime templates rerender on url change (#1528)
1 parent 310be3e commit 0030755

6 files changed

Lines changed: 23 additions & 4 deletions

File tree

znai-docs/znai/release-notes/1.90/add-2026-04-24-user-defined-plugins.md

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* Fix: [Runtime Templates](layout/runtime-templates) re-renders on url change

znai-reactjs/src/doc-elements/cli/CliCommand.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import React, { useState, useEffect, useMemo } from "react";
2020
import CliCommandToken from "./CliCommandToken";
2121
import { splitParts } from "../../utils/strings";
2222
import { DocElementPayload } from "../default-elements/DocElement";
23-
import { resolveTemplateText } from "../url-query-value/queryParamTemplate";
23+
import { resolveTemplateText, useUrlQuerySubscription } from "../url-query-value/queryParamTemplate";
2424
import "./CliCommand.css";
2525

2626
interface Token {
@@ -53,6 +53,7 @@ const CliCommand: React.FC<CliCommandProps> = ({
5353
splitAfter = [],
5454
templateUseQueryParam = false,
5555
}) => {
56+
useUrlQuerySubscription();
5657
const resolvedCommand = templateUseQueryParam ? resolveTemplateText(command) : command;
5758
const tokens = useMemo(() => tokenize(resolvedCommand), [resolvedCommand]);
5859

znai-reactjs/src/doc-elements/code-snippets/Snippet.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import { parseCode } from "./codeParser";
3535
import { countNumberOfLines } from "../../utils/strings";
3636

3737
import { SnippetBulletExplanations } from "./explanations/SnippetBulletExplanations";
38-
import { resolveTemplateText } from "../url-query-value/queryParamTemplate";
38+
import { resolveTemplateText, useUrlQuerySubscription } from "../url-query-value/queryParamTemplate";
3939

4040
import "./Snippet.css";
4141

@@ -45,6 +45,7 @@ const BULLETS_COMMENT_TYPE = "inline";
4545
const REMOVE_COMMENT_TYPE = "remove";
4646

4747
const Snippet = (props) => {
48+
useUrlQuerySubscription();
4849
const snippet = props.templateUseQueryParam ? resolveTemplateText(props.snippet) : props.snippet;
4950
const tokensToUse = parseCodeWithCompatibility({ lang: props.lang, snippet, tokens: props.tokens });
5051

znai-reactjs/src/doc-elements/url-query-value/UrlQueryValue.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
import React from "react";
1818

19-
import { resolveQueryParamValue } from "./queryParamTemplate";
19+
import { resolveQueryParamValue, useUrlQuerySubscription } from "./queryParamTemplate";
2020

2121
import "./UrlQueryValue.css";
2222

@@ -26,6 +26,7 @@ interface Props {
2626
}
2727

2828
export function UrlQueryValue({ queryParam, default: defaultValue }: Props) {
29+
useUrlQuerySubscription();
2930
const resolved = resolveQueryParamValue(queryParam, defaultValue);
3031

3132
if (resolved.isMissing) {

znai-reactjs/src/doc-elements/url-query-value/queryParamTemplate.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,24 @@
1414
* limitations under the License.
1515
*/
1616

17+
import { useEffect, useReducer } from "react";
18+
import { documentationNavigation } from "../../structure/DocumentationNavigation";
19+
1720
const TEMPLATE_PATTERN = /\$\{([^}]+)}/g;
1821

22+
// subscribes the calling component to URL changes so it re-renders when the
23+
// query string changes — query-param-driven content stays in sync even when
24+
// an ancestor's shouldComponentUpdate would otherwise skip the re-render.
25+
// TODO: switch to useSyncExternalStore once React is upgraded to 18+.
26+
export function useUrlQuerySubscription(): void {
27+
const [, forceUpdate] = useReducer((x: number) => x + 1, 0);
28+
29+
useEffect(() => {
30+
documentationNavigation.addUrlChangeListener(forceUpdate);
31+
return () => documentationNavigation.removeUrlChangeListener(forceUpdate);
32+
}, []);
33+
}
34+
1935
export function resolveQueryParamValue(
2036
paramName: string,
2137
defaultValue?: string

0 commit comments

Comments
 (0)