Skip to content

Commit

Permalink
feat: useInlineRender hook (#1025)
Browse files Browse the repository at this point in the history
  • Loading branch information
Yonom authored Oct 19, 2024
1 parent d181185 commit ba5116f
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 19 deletions.
5 changes: 5 additions & 0 deletions .changeset/slimy-socks-unite.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@assistant-ui/react": patch
---

feat: useInlineRender hook
9 changes: 4 additions & 5 deletions apps/docs/content/docs/advanced/ToolUI.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -92,19 +92,18 @@ const MyApp = () => {

### Inline Tool UI Hooks

If you need access to component props, you can use the `useAssistantToolUI` hook.
If you need access to component props, you can use the `useAssistantToolUI` hook. If you are passing a component inline, you should use the `useInlineRender` hook to prevent the component from being re-mounted on every render.

```tsx {5-11}
import { useAssistantToolUI } from "@assistant-ui/react";
import { useCallback } from "react";
import { useAssistantToolUI, useInlineRender } from "@assistant-ui/react";

const MyComponent = ({ product_id }) => {
useAssistantToolUI({
toolName: "current_product_info",
render: useCallback(({ args, status }) => {
render: useInlineRender(({ args, status }) => {
// you can access component props here
return <p>product_info({ product_id })</p>;
}, [product_id]),
}),
});

...
Expand Down
3 changes: 2 additions & 1 deletion packages/react/src/context/stores/AssistantToolUIs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

import { create } from "zustand";
import type { ToolCallContentPartComponent } from "../../types/ContentPartComponentTypes";
import { Unsubscribe } from "../../types";

export type AssistantToolUIsState = Readonly<{
getToolUI: (toolName: string) => ToolCallContentPartComponent | null;
setToolUI: (
toolName: string,
render: ToolCallContentPartComponent,
) => () => void;
) => Unsubscribe;
}>;

export const makeAssistantToolUIsStore = () =>
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/model-config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export {
useAssistantToolUI,
type AssistantToolUIProps,
} from "./useAssistantToolUI";
export { useInlineRender } from "./useInlineRender";
20 changes: 10 additions & 10 deletions packages/react/src/model-config/useAssistantTool.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,22 @@ export const useAssistantTool = <
) => {
const assistantRuntime = useAssistantRuntime();
const toolUIsStore = useToolUIsStore();

useEffect(() => {
return tool.render
? toolUIsStore.getState().setToolUI(tool.toolName, tool.render)
: undefined;
}, [toolUIsStore, tool.toolName, tool.render]);

useEffect(() => {
const { toolName, render, ...rest } = tool;
const config = {
tools: {
[tool.toolName]: rest,
[toolName]: rest,
},
};
const unsub1 = assistantRuntime.registerModelConfigProvider({
return assistantRuntime.registerModelConfigProvider({
getModelConfig: () => config,
});
const unsub2 = render
? toolUIsStore.getState().setToolUI(toolName, render)
: undefined;
return () => {
unsub1();
unsub2?.();
};
}, [assistantRuntime, toolUIsStore, tool]);
}, [assistantRuntime, tool]);
};
6 changes: 3 additions & 3 deletions packages/react/src/model-config/useAssistantToolUI.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ export type AssistantToolUIProps<
};

export const useAssistantToolUI = (
// TODO remove null option in 0.6
tool: AssistantToolUIProps<any, any> | null,
) => {
const toolUIsStore = useToolUIsStore();
useEffect(() => {
if (!tool) return;
const { toolName, render } = tool;
return toolUIsStore.getState().setToolUI(toolName, render);
}, [toolUIsStore, tool]);
return toolUIsStore.getState().setToolUI(tool.toolName, tool.render);
}, [toolUIsStore, tool?.toolName, tool?.render]);
};
18 changes: 18 additions & 0 deletions packages/react/src/model-config/useInlineRender.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { FC, useCallback, useEffect, useState } from "react";
import { ToolCallContentPartProps } from "../types";
import { create } from "zustand";

export const useInlineRender = <TArgs extends Record<string, unknown>, TResult>(
toolUI: FC<ToolCallContentPartProps<TArgs, TResult>>,
): FC<ToolCallContentPartProps<TArgs, TResult>> => {
const [useToolUI] = useState(() => create(() => toolUI));

useEffect(() => {
useToolUI.setState(toolUI);
});

return useCallback((args) => {
const toolUI = useToolUI();
return toolUI(args);
}, []);
};

0 comments on commit ba5116f

Please sign in to comment.