Skip to content

feat: add shared memo client for react embeds#6

Merged
markbang merged 1 commit into
mainfrom
feat/shared-memo-client-followup
Mar 9, 2026
Merged

feat: add shared memo client for react embeds#6
markbang merged 1 commit into
mainfrom
feat/shared-memo-client-followup

Conversation

@markbang
Copy link
Copy Markdown
Owner

@markbang markbang commented Mar 9, 2026

Summary

  • add createMemoClient() in core for cross-embed memo and creator request deduping
  • add MemoClientProvider and useMemoClient() in @memos-embed/react, wiring both MemoEmbed and MemoEmbedList into shared client usage
  • document the shared-client workflow across README, package docs, and site docs, and keep pack-smoke coverage aligned

Testing

  • pnpm validate

Summary by cubic

Adds a shared memo client to memos-embed with a React provider/hook so multiple embeds reuse memo/creator requests and avoid duplicate fetches. Docs and tests were updated to cover the new workflow.

  • New Features
    • memos-embed: createMemoClient() with in-memory caching, fetchMemo/fetchMemos, primeMemo/primeMemos, and clear().
    • @memos-embed/react: MemoClientProvider and useMemoClient(); MemoEmbed and MemoEmbedList accept an optional client prop and use the shared client when available (prefetched data is primed into the client; without a client, existing per-component fetch/abort behavior remains).
    • Docs updated with “Shared React memo client” examples; tests and pack-smoke scripts validate new exports and provider flow.

Written for commit 3793df7. Summary will update on new commits.

@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 9, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
memos-embed-site Ready Ready Preview, Comment Mar 9, 2026 9:12am

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

3 issues found across 13 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/memos-embed-react/src/index.tsx">

<violation number="1" location="packages/memos-embed-react/src/index.tsx:109">
P1: `useContext` is called conditionally in `useMemoClient`, which can break hook ordering across renders.</violation>
</file>

<file name="packages/memos-embed/src/api.ts">

<violation number="1" location="packages/memos-embed/src/api.ts:158">
P1: Shared user caching is keyed only by user ID, so one `createMemoClient` used across multiple `baseUrl` values can return creator data from the wrong instance.</violation>

<violation number="2" location="packages/memos-embed/src/api.ts:315">
P2: `createMemoClient().fetchMemo` drops the `signal` option, so abort/cancellation passed by callers is silently ignored.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

);

export const useMemoClient = (client?: MemoClient) =>
client ?? useContext(MemoClientContext);
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Mar 9, 2026

Choose a reason for hiding this comment

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

P1: useContext is called conditionally in useMemoClient, which can break hook ordering across renders.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/memos-embed-react/src/index.tsx, line 109:

<comment>`useContext` is called conditionally in `useMemoClient`, which can break hook ordering across renders.</comment>

<file context>
@@ -86,6 +91,23 @@ export type MemoEmbedListProps =
+);
+
+export const useMemoClient = (client?: MemoClient) =>
+	client ?? useContext(MemoClientContext);
+
 const renderState = ({
</file context>
Fix with Cubic

const normalizedBaseUrl = normalizeBaseUrl(baseUrl);
const id = userId.includes("/") ? getIdFromName(userId) : userId;
const cached = context.userCache.get(id);
const cached = userCache.get(id);
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Mar 9, 2026

Choose a reason for hiding this comment

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

P1: Shared user caching is keyed only by user ID, so one createMemoClient used across multiple baseUrl values can return creator data from the wrong instance.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/memos-embed/src/api.ts, line 158:

<comment>Shared user caching is keyed only by user ID, so one `createMemoClient` used across multiple `baseUrl` values can return creator data from the wrong instance.</comment>

<file context>
@@ -114,37 +133,38 @@ const normalizeMemo = (
+	const normalizedBaseUrl = normalizeBaseUrl(baseUrl);
 	const id = userId.includes("/") ? getIdFromName(userId) : userId;
-	const cached = context.userCache.get(id);
+	const cached = userCache.get(id);
 	if (cached) {
 		return cached;
</file context>
Fix with Cubic

Comment on lines +315 to +328
const clientFetchMemo: MemoClient["fetchMemo"] = async ({
baseUrl,
memoId,
includeCreator = true,
fetcher,
}) =>
fetchMemoWithCache({
baseUrl,
memoId,
includeCreator,
fetcher: fetcher ?? config.fetcher ?? fetch,
userCache,
memoCache,
});
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Mar 9, 2026

Choose a reason for hiding this comment

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

P2: createMemoClient().fetchMemo drops the signal option, so abort/cancellation passed by callers is silently ignored.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/memos-embed/src/api.ts, line 315:

<comment>`createMemoClient().fetchMemo` drops the `signal` option, so abort/cancellation passed by callers is silently ignored.</comment>

<file context>
@@ -191,33 +225,144 @@ const fetchMemoWithContext = async ({
+	const memoCache: MemoCache = new Map();
+	const userCache: UserCache = new Map();
+
+	const clientFetchMemo: MemoClient["fetchMemo"] = async ({
+		baseUrl,
+		memoId,
</file context>
Suggested change
const clientFetchMemo: MemoClient["fetchMemo"] = async ({
baseUrl,
memoId,
includeCreator = true,
fetcher,
}) =>
fetchMemoWithCache({
baseUrl,
memoId,
includeCreator,
fetcher: fetcher ?? config.fetcher ?? fetch,
userCache,
memoCache,
});
const clientFetchMemo: MemoClient["fetchMemo"] = async ({
baseUrl,
memoId,
includeCreator = true,
fetcher,
signal,
}) =>
fetchMemoWithCache({
baseUrl,
memoId,
includeCreator,
fetcher: fetcher ?? config.fetcher ?? fetch,
signal,
userCache,
memoCache,
});
Fix with Cubic

@markbang markbang merged commit 8a0d603 into main Mar 9, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant