logoassistant-ui

Using old React versions

Older React Versions

Older React versions are not continuously tested. If you encounter any issues with integration, please contact us for help by joining our Discord.

This guide provides instructions for configuring assistant-ui to work with React 18 or older versions.

React 18

If you're using React 18, you need to update the shadcn/ui components to work with forwardRef. Specifically, you need to modify the Button component.

Updating the Button Component

Navigate to your button component file (typically /components/ui/button.tsx) and wrap the Button component with forwardRef:

// Before
function Button({
  className,
  variant,
  size,
  asChild = false,
  ...props
}: React.ComponentProps<"button"> &
  VariantProps<typeof buttonVariants> & {
    asChild?: boolean;
  }) {
  const Comp = asChild ? Slot : "button";

  return (
    <Comp
      data-slot="button"
      className={cn(buttonVariants({ variant, size, className }))}
      {...props}
    />
  );
}

// After
const Button = React.forwardRef<
  HTMLButtonElement,
  React.ComponentProps<"button"> &
    VariantProps<typeof buttonVariants> & {
      asChild?: boolean;
    }
>(({ className, variant, size, asChild = false, ...props }, ref) => {
  const Comp = asChild ? Slot : "button";

  return (
    <Comp
      data-slot="button"
      className={cn(buttonVariants({ variant, size, className }))}
      ref={ref}
      {...props}
    />
  );
});
Button.displayName = "Button";

Note: If you're using a lower React version (17 or 16), you'll also need to follow the instructions for that version.

React 17

For React 17 compatibility, in addition to the modifications outlined for React 18, you must also include a polyfill for the useSyncExternalStore hook (utilized by zustand).

Patching Zustand with patch-package

Since the assistant-ui uses zustand internally, which depends on useSyncExternalStore, you'll need to patch the zustand package directly:

  1. Install the required packages:
npm install use-sync-external-store patch-package
# or
yarn add use-sync-external-store patch-package
  1. Add a postinstall script to your package.json:
{
  "scripts": {
    "postinstall": "patch-package"
  }
}
  1. You'll want to follow the instructions in patch-package, by first making changes to the files of a particular package in your node_modules folder, then running either yarn patch-package package-name or npx patch-package package-name. You'll need a patch for zustand - within node_modules/zustand, open zustand/react.js and make the following code changes:
diff --git a/node_modules/zustand/react.js b/node_modules/zustand/react.js
index 7599cfb..64530a8 100644
--- a/node_modules/zustand/react.js
+++ b/node_modules/zustand/react.js
@@ -1,6 +1,6 @@
 'use strict';

-var React = require('react');
+var React = require('use-sync-external-store/shim');
 var vanilla = require('zustand/vanilla');

 const identity = (arg) => arg;
@@ -10,7 +10,7 @@ function useStore(api, selector = identity) {
     () => selector(api.getState()),
     () => selector(api.getInitialState())
   );
-  React.useDebugValue(slice);
+  //React.useDebugValue(slice);
   return slice;
 }
 const createImpl = (createState) => {

This patch replaces the React import in zustand with the polyfill from `use-sync-external-store/shim` and comments out the `useDebugValue` call which isn't needed.

You should then run the patch-package command `yarn patch-package zustand` or `npx patch-package zustand` which should create a `patches` folder with a zustand patch file similar looking to this:

```diff
diff --git a/node_modules/zustand/react.js b/node_modules/zustand/react.js
index 7599cfb..64530a8 100644
--- a/node_modules/zustand/react.js
+++ b/node_modules/zustand/react.js
@@ -1,6 +1,6 @@
 'use strict';

-var React = require('react');
+var React = require('use-sync-external-store/shim');
 var vanilla = require('zustand/vanilla');

 const identity = (arg) => arg;
@@ -10,7 +10,7 @@ function useStore(api, selector = identity) {
     () => selector(api.getState()),
     () => selector(api.getInitialState())
   );
-  React.useDebugValue(slice);
+  //React.useDebugValue(slice);
   return slice;
 }
 const createImpl = (createState) => {
  1. You may also need to apply the same patches within node_modules/@assistant-ui/react/ and possibly a nested dependency patch for node_modules/@assistant-ui/react/node_modules/zustand. Look for instances of React.useSyncExternalStore and replace with { useSyncExternalStore } from "use-sync-external-store/shim"; and comment out any useDebugValue calls. Finally, you may need to patch useId from React, so within node_modules/@assistant-ui/react/dist/runtimes/remote-thread-list/RemoteThreadListThreadListRuntimeCore.js, change the following:
-import { Fragment, useEffect, useId } from "react";
+import { Fragment, useEffect, useRef } from "react";
 import { create } from "zustand";
 import { AssistantMessageStream } from "assistant-stream";
 import { RuntimeAdapterProvider } from "../adapters/RuntimeAdapterProvider.js";
 import { jsx } from "react/jsx-runtime";
+
+// PATCH-PACKAGE: Polyfill for useId if not available in React 16
+let useId;
+try {
+  // Try to use React's useId if available
+  useId = require("react").useId;
+} catch (e) {}
+if (!useId) {
+  // Fallback polyfill
+  let globalId = 0;
+  useId = function() {
+    const idRef = useRef();
+    if (!idRef.current) {
+      globalId++;
+      idRef.current = `uid-${globalId}`;
+    }
+    return idRef.current;
+  };
+}
  1. Run the postinstall script to apply the patches:
npm run postinstall
# or
yarn postinstall

This patch replaces the React import in zustand with the polyfill from use-sync-external-store/shim and comments out the useDebugValue call which isn't needed.

Note: If you're using React 16, you'll also need to follow the instructions for that version.

React 16

Incomplete Section

This section is incomplete and contributions are welcome. If you're using React 16 and have successfully integrated assistant-ui, please consider contributing to this documentation.

For React 16 compatibility, you need to apply all the steps for React 18 and React 17 above.

Additional Resources

If you encounter any issues with React compatibility, please:

  1. Check that all required dependencies are installed
  2. Ensure your component modifications are correctly implemented
  3. Join our Discord community for direct support