tjtanjin / react-chatbotify

A modern React library for creating a flexible and extensible chatbot.
https://react-chatbotify.com
MIT License
135 stars 65 forks source link

[Bug] ReferenceError: window is not defined and flow not working and flow not working properly #19

Closed nellysbr closed 5 months ago

nellysbr commented 5 months ago

Bug Description

Hello! I am having the error below when i use chatbotify with Nextjs (yes i am using "use client" on the component). This error is happening everytime when a refresh the page. Yet the flow is not working properly.

//console error

⨯ node_modules\react-chatbotify\dist\index.js (914:1) @ eval ⨯ ReferenceError: window is not defined at __webpack_require__ (C:\Users\Suave\Documents\sandbox\suave-chat-bot-v2\.next\server\webpack-runtime.js:33:42) at eval (./src/components/SuaveChatBot/SuaveChatBot.tsx:9:74) at (ssr)/./src/components/SuaveChatBot/SuaveChatBot.tsx (C:\Users\Suave\Documents\sandbox\suave-chat-bot-v2\.next\server\app\page.js:173:1) at __webpack_require__ (C:\Users\Suave\Documents\sandbox\suave-chat-bot-v2\.next\server\webpack-runtime.js:33:42) at eval (./src/app/page.tsx:7:95) at (ssr)/./src/app/page.tsx (C:\Users\Suave\Documents\sandbox\suave-chat-bot-v2\.next\server\app\page.js:162:1) at __webpack_require__ (C:\Users\Suave\Documents\sandbox\suave-chat-bot-v2\.next\server\webpack-runtime.js:33:42) at JSON.parse (<anonymous>) null

//Component code.

` "use client"; import React, { useState } from "react"; import ChatBot from "react-chatbotify";

const SuaveChatBot = () => { const [form, setForm] = useState({}); const flow = { start: { message: "Olá! Tudo bem ? Meu nome é Érica", function: (params: any) => setForm({ ...form, name: params.userInput }), path: "presentation", }, presentation: { message: "Tenho ótimos negócios este mês para sair com seu novo Audi.", path: "ask_name", }, ask_name: { message: "Mas antes de prosseguir, preciso de algumas informações. Qual é o seu nome?", chatDisabled: false, path: "end", }, end: { message: (params: any) => I see you are ${params.userInput}!, chatDisabled: true, }, }; return ( <>

</>

); };

export default SuaveChatBot; `

Steps To Reproduce Steps to reproduce the bug behavior:

  1. Start a new clean Nextjs Project
  2. Import the bot css on layout.tsx
  3. Create a new component (e.g MyCustomBot.tsx)
  4. Set "use client" at the top
  5. Import the component to your desired page

Expected behavior You can see on the console the error mentioned above

Desktop (please complete the following information):

  • OS: [Windows 11]
  • Browser: chrome
tjtanjin commented 5 months ago

Hey @nellysbr! Let me take a look at it, I'll get back to you soon.

nellysbr commented 5 months ago

Thanks for your support and hard work!

tjtanjin commented 5 months ago

Hey @nellysbr, so I did a little digging. Basically, since NextJS is a server-side rendering framework, the window object may not be available immediately. To resolve this, load the ChatBot lazily. Refer to code snippet below for an example:

"use client";
import { lazy, Suspense, useEffect, useState } from "react"

export default function Home() {
  const ChatBot = lazy(() => import("react-chatbotify"));
  const [isLoaded, setIsLoaded] = useState(false);
  useEffect(() => {
    setIsLoaded(true);
  }, [])

  return (
    <>
    {isLoaded && (
      <Suspense fallback={<div>Loading...</div>}>
        <ChatBot />
      </Suspense>
    )}
    </>
  );
}

I did consider addressing this directly within the library itself but the use of window, navigator and document appears in quite a number of places which makes it impossible to resolve in the library without making the code bloat up and overall look very ugly. Let me know if the suggested approach above address your issue!

nellysbr commented 5 months ago

Thanks for your hard work! Your solution fix this specific issue! But i have another problem after applying this. Its kinda another bug. Following your docs i am building the bot flow with a basic form. However, the bot is not waiting for the user input to proceed to the next step of the chat. For example, in 'ask_name', it moves to the next step of the flow without waiting for the user to type their name. I don't know if this is actually a bug or if it's some configuration that I'm forgetting to add. Below is the code (already applying your previous solution):


"use client";
import React, { useState, useEffect, lazy, Suspense } from "react";
const ChatBot = lazy(() => import("react-chatbotify"));

const SuaveChatBot = () => {
  const [form, setForm] = useState({});
  const [isLoaded, setIsLoaded] = useState(false);

  useEffect(() => {
    setIsLoaded(true);
  }, []);

  const subjectOptions = [
    "Veículos Novos",
    "Veículos Seminovos",
    "Pós-vendas",
    "Consórcio",
  ];
  const flow = {
    start: {
      message: "Olá! Tudo bem ? Meu nome é Érica",
      transition: { duration: 1000 },
      chatDisabled: true,
      path: "presentation",
    },
    presentation: {
      message: "Tenho ótimos negócios este mês para sair com seu novo Audi.",
      transition: { duration: 2000 },
      chatDisabled: true,
      path: "ask_name",
    },
    ask_name: {
      message:
        "Mas antes de prosseguir, preciso de algumas informações. Qual é o seu nome?",
      transition: { duration: 3000 },
      function: (params: any) => setForm({ ...form, name: params.userInput }),
      path: "ask_subject",
    },
    ask_subject: {
      message: (params: any) =>
        `Obrigada, ${params.userInput}! Qual assunto, você deseja tratar?`,
      chatDisabled: true,
      transition: { duration: 4000 },
      options: subjectOptions,
      function: (params: any) =>
        setForm({ ...form, subject: params.userInput }),
      path: "end",
    },
    end: {
      message: (params: any) =>
        `Obrigada ${params.userInput}, vou entrar em contato com você em breve!`,
      transition: { duration: 5000 },
      chatDisabled: true,
    },
  };
  return (
    <>
      {isLoaded && (
        <Suspense fallback={<div>Loading...</div>}>
          <ChatBot flow={flow} />
        </Suspense>
      )}
    </>
  );
};

export default SuaveChatBot;
tjtanjin commented 5 months ago

Hey @nellysbr! Glad you're making progress. With regards to why ask_name is not waiting for user input before proceeding, it's because you have this: transition: { duration: 3000 }. Basically after 3 seconds, it is transitioning to the next path (ask_subject). If you would like to wait for user input, then you do not actually need transition.

nellysbr commented 5 months ago

I really appreciate for your help!

Thanks for all your support and for keeping this aweasome project!

tjtanjin commented 5 months ago

I really appreciate for your help!

Thanks for all your support and for keeping this aweasome project!

No problem! I've updated the FAQ in case anyone else comes across a similar issue as you in future, thank you for raising it up!

kavin-bytive commented 4 months ago

i also want to use BotOptionsContext and getDefaultBotOptions, but seems they are not loading via lazyload, any way to fix it ?

@tjtanjin

tjtanjin commented 4 months ago

i also want to use BotOptionsContext and getDefaultBotOptions, but seems they are not loading via lazyload, any way to fix it ?

@tjtanjin

Hey @kavin-bytive! Perhaps you can create a new issue and attach the screenshots or code snippet for your use-case then I can help take a look 😄

kavin-bytive commented 4 months ago

sure, here is the link https://github.com/tjtanjin/react-chatbotify/issues/32