OvidijusParsiunas / deep-chat

Fully customizable AI chatbot component for your website
https://deepchat.dev
MIT License
1.27k stars 176 forks source link

React/NextJS - useState refreshes the chat #61

Closed succinct0274 closed 6 months ago

succinct0274 commented 7 months ago

Hi @OvidijusParsiunas, I found that the use of useState function in the handler or interceptor will cause the reload of the page and the messages will be all lost. Below is a code snippet that can reproduce the issue given your nextjs example provided in example-servers directory:

  const [talked, setTalked] = useState(false);

  return ( ...
          <DeepChat
            style={{borderRadius: '10px'}}
            introMessage={{text: 'Send a chat message to an example server.'}}
            request={{
              handler: (body, signals) => {
                try {
                  fetch('/api/custom/chat', {method: 'POST', 'body': JSON.stringify(body)}).then(async res => {
                    setTalked(!talked)
                    const json = await res.json()
                    signals.onResponse({
                      'text': JSON.stringify(json)
                    })
                  })
                } catch(err) {
                  signals.onResponse({error: 'Error'});
                }
              }
            }}.../>
  ...)

I am not pretty sure the what root cause is. It would be great if you can give some advices to circumvent this. Thank you so much in advance.

OvidijusParsiunas commented 7 months ago

Hi @succinct0274. The state hook (useState) automatically re-renders the component. If Deep Chat is inside this component, it will also be re-rendered from scratch.

There are multiple ways you can prevent this from happening:

  1. Simply store your state in a variable like - let talked = false;
  2. Store your state in sessionStorage or localStorage
  3. Use the redux library to store state
  4. Store state using any other browser state storage solution or even store it in an external API depending on your needs.

This is a common problem when working with React/NextJs and hopefully the above solutions help. Let me know if you need more assistance. Thanks!

OvidijusParsiunas commented 6 months ago

I will be closing this issue due to no recent activity on it. If you have any further questions in regards to the same topic - feel free to comment below, otherwise you can create a new issue. Thanks!

colelin26 commented 6 months ago

My solution is to use Memo to skip re-rendering when props don't change.

Basically, define this outside of the component

const MemoDeepChat = memo(DeepChat);

function MyComponet() {
  <MemoDeepChat .../>
}

and make sure the props don't change. Note that for array and object props we need to make sure a new object is not created in a render.