Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issues while referencing DeepChat element #99

Closed
K-Jadeja opened this issue Jan 18, 2024 · 5 comments
Closed

Issues while referencing DeepChat element #99

K-Jadeja opened this issue Jan 18, 2024 · 5 comments
Assignees
Labels
advice Information how to use/implement the component

Comments

@K-Jadeja
Copy link

I've been following issue #59 and am trying to wrap the DeepChat element and reference the wrapper element. I am trying to get your first suggestion to work with my code but I am facing a lot of errors like Property 'children' does not exist on type 'never' and 'ref.current' is possibly 'null'.

Sorry, I am new to typescript and would really appreciate any help getting this to work
My code:

import React, { useEffect } from 'react';
import Box from '@mui/material/Box';
import dynamic from 'next/dynamic';
import { useUser } from '@clerk/nextjs';
import { RequestInterceptor, ResponseInterceptor } from 'deep-chat/dist/types/interceptors';
import { DeepChat as DeepChatCore } from 'deep-chat';

const DeepChat = dynamic(() => import('deep-chat-react').then((mod) => mod.DeepChat), {
  ssr: false,
});

export const ChatComponent = () => {
  const { user } = useUser();
  const ref = React.useRef(null);

  useEffect(() => {
    setTimeout(() => {
      if (ref.current) {
        const component = ref.current.children[0] as DeepChatCore;
        component.initialMessages = [
          { role: 'user', text: 'Hi' },
          { role: 'ai', text: 'Bye' },
        ];
      }
    });
  }, []);

  const requestInterceptor: RequestInterceptor = (details) => {
    details.body = {
      input: {
        text: details.body.messages[0].text,
      },
      config: {},
      kwargs: {},
    };
    return details;
  };

  const responseInterceptor: ResponseInterceptor = (details) => {
    // console.log(details);
    return { text: details.content || '' };
  };

  return (
    <Box
      display="flex"
      justifyContent="space-between"
      alignItems="center"
      // mb={2}
    >
      <div ref={ref}>
        <DeepChat
          request={{ url: 'https://test.up.railway.app/test/stream' }}
          requestInterceptor={requestInterceptor}
          responseInterceptor={responseInterceptor}
          requestBodyLimits={{ maxMessages: -1 }}
          stream={true}
        />
      </div>
    </Box>
  );
};

export default ChatComponent;

My main aim is to use methods like getMessages() to store and retrieve chat history from a database.

Thanks

@OvidijusParsiunas
Copy link
Owner

OvidijusParsiunas commented Jan 18, 2024

Hi @K-Jadeja.
If you want to apply certain properties to Deep Chat as soon as it renders, I would highly recommend using the onComponentRender event. That way you do not have to set an arbitrary timeout and can know exactly when the reference is available.

So your code would look something like this:

let isSet = false;

return (
  <div ref={ref}>
    <DeepChat
      onComponentRender={() => {
        if (!isSet) {
          const component = ref.current.children[0] as DeepChatCore;
          component.initialMessages = [
            {role: 'user', text: 'Hi'},
            {role: 'ai', text: 'Bye'},
          ];
          isSet = true;
        }
      }}
      request={{url: 'https://test.up.railway.app/test/stream'}}
      requestInterceptor={requestInterceptor}
      responseInterceptor={responseInterceptor}
      requestBodyLimits={{maxMessages: -1}}
      stream={true}
    />
  </div>
);

The isSet variable is used to prevent infinite recursion as onComponentRender is triggered every time a property is set.

Let me know if you need any further assistance.

I have thought about this a little more and will update the onComponentRender event to pass the actual component as an argument, so it would be easier to access it. I'll include it in the next release.
For now, the above example should work just fine.

@OvidijusParsiunas OvidijusParsiunas self-assigned this Jan 18, 2024
@OvidijusParsiunas OvidijusParsiunas added the advice Information how to use/implement the component label Jan 18, 2024
@K-Jadeja
Copy link
Author

Thanks @OvidijusParsiunas!

The code works but I still get these errors Property 'children' does not exist on type 'never' and 'ref.current' is possibly 'null'.
image

Did I miss something?

@OvidijusParsiunas
Copy link
Owner

My apologies, for some reason the example NextJs project wasn't giving me that Type error.
Please use the following code for better Type inference:

const ref = React.useRef<HTMLDivElement>(null);

let isSet = false;

return (
 <div ref={ref}>
    <DeepChat
      onComponentRender={() => {
        if (!isSet && ref.current) {
          const component = ref.current.children[0] as DeepChatCore;
          component.initialMessages = [
            {role: 'user', text: 'Hi'},
            {role: 'ai', text: 'Bye'},
          ];
          isSet = true;
        }
      }}
      request={{url: 'https://test.up.railway.app/test/stream'}}
      requestInterceptor={requestInterceptor}
      responseInterceptor={responseInterceptor}
      requestBodyLimits={{maxMessages: -1}}
      stream={true}
    />
  </div>
);

@K-Jadeja
Copy link
Author

Thank you so much @OvidijusParsiunas! It works now :)

@OvidijusParsiunas
Copy link
Owner

Happy to hear it helped! I will close this issue. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
advice Information how to use/implement the component
Projects
None yet
Development

No branches or pull requests

2 participants