FredrikOseberg / react-chatbot-kit

MIT License
325 stars 156 forks source link

Question: Is there any way to send props from the Parent Component to Chatbot? #42

Open naman-gupta99 opened 3 years ago

naman-gupta99 commented 3 years ago

I am trying to build a bot that uses the context that which user is accessing the chatbot and from which page in the website. But for this I either have to pass props into the Chatbot (which it doesn't accept) or create a Context and then use that value in the ActionProvider class (again which I can't because ActionProvider is not a Component).

Is there any way of going about this?

FredrikOseberg commented 3 years ago

Hi. Not sure I'm understanding your use case. Can you elaborate?

fre. 26. mar. 2021 kl. 17:28 skrev TheMaroonKnight @.***

:

I am trying to build a bot that uses the context that which user is accessing the chatbot and from which page in the website. But for this I either have to pass props into the Chatbot (which it doesn't accept) or create a Context and then use that value in the ActionProvider class (again which I can't because ActionProvider is not a Component).

Is there any way of going about this?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/FredrikOseberg/react-chatbot-kit/issues/42, or unsubscribe https://github.com/notifications/unsubscribe-auth/AD2WIPRCMZJF5YXFKRBE3NDTFSY37ANCNFSM4Z3WOCCQ .

naman-gupta99 commented 3 years ago

So, image

This is my website. I want to change the responses to user questions on the basis of which page the user is currently on and if the user is logged in or not.

Now the Page Name and the Auth Status are stored as State variables in the App Component (Where is present). So, how can I send these data items to actionProviders, so that it could use it to determine the response?

FredrikOseberg commented 3 years ago

So, image

This is my website. I want to change the responses to user questions on the basis of which page the user is currently on and if the user is logged in or not.

Now the Page Name and the Auth Status are stored as State variables in the App Component (Where is present). So, how can I send these data items to actionProviders, so that it could use it to determine the response?

Got it. Currently, you can't pass props to the actionprovider from the chatbot. I'll look into supporting that in the future. Meanwhile, what you could do is mirror them into the state of the chatbot using a dynamic config:

const getConfig = (authStatus, pageName) => {
   return {
      initialMessages: [createChatbotMessage("Hi"]
      state: {
           authStatus: appState,
           pageName: appState
      }
   }
}

<Chatbot ... config={getConfig(authStatus, pageName)} />

Now you should be able to access the variables through the setState function in the action provider:

this.setState(state => {
      if (state.authStatus && state.pageName === "something") {
           // do logic
      }
})
naman-gupta99 commented 3 years ago

Hey! I just realized there is another problem with this. So, I won't be able to something when the state changes. For example, if I want to update the questions whenever the page changes, how could we do that?

If we call the handler function inside the constructor that will create an infinite loop as the handler will change the state which in turn would rerender the chatbot and then it would recreate ActionProvider object and hence call the constructor.

Can you think of some other way to solve this?

FredrikOseberg commented 3 years ago

Hey! I just realized there is another problem with this. So, I won't be able to something when the state changes. For example, if I want to update the questions whenever the page changes, how could we do that?

If we call the handler function inside the constructor that will create an infinite loop as the handler will change the state which in turn would rerender the chatbot and then it would recreate ActionProvider object and hence call the constructor.

Can you think of some other way to solve this?

If you want to change the options whenever the page changes you can map the state to the options widget in the config:

const getConfig = (authStatus, pageName) => {
   return {
      initialMessages: [createChatbotMessage("Hi"]
      state: {
           authStatus: appState,
           pageName: appState
      },
      widgets: [
           {
              widget: (props) => <Options {...props} />,
              widgetName: "options",
              mapStateToProps: ["pageName"]
           }
      ]
   }
}

Then you should have the pagename available to the options widget and can use it to change the options data. Is that what you wanted to achieve?

naman-gupta99 commented 3 years ago

Yes that's exactly it. Also, I can see that it using a single instance of the widget component to render it wherever it needs to be used.

For eg. This is my Options widget code : image

This is what shows up when I open the chatbot for the first time: image

These are the screenshots when I change the tab and then type in a message: image image

The problem now is that when the 'options' widget is used again it gets updated for all the instances of itself in the chatbot conversation.

naman-gupta99 commented 3 years ago

There's another problem, when the props of the parent changes and it re-renders chatbot the change in the value of props shows up inside the config but not inside the actual state of the chatbot component.

image

Edit 1: I went through the Chatbot.jsx in the node_modules and realized that even if the value changes inside the config.js when the state changes for the parent component that won't mean that the state for the chatbot would change because only getInitialState accesses the value inside the config which isn't called inside onEffect and hence no change.

FredrikOseberg commented 3 years ago

Yes that's exactly it. Also, I can see that it using a single instance of the widget component to render it wherever it needs to be used.

For eg. This is my Options widget code : image

This is what shows up when I open the chatbot for the first time: image

These are the screenshots when I change the tab and then type in a message: image image

The problem now is that when the 'options' widget is used again it gets updated for all the instances of itself in the chatbot conversation.

Right. That's a consequence of how React works. You can change how this works by setting different properties of state and rendering from different state data. Otherwise React will use the same data and update the widget. What you need to do in your case is set different state properties and wrap the options component in a wrapper that decides which state to update.

FredrikOseberg commented 3 years ago

There's another problem, when the props of the parent changes and it re-renders chatbot the change in the value of props shows up inside the config but not inside the actual state of the chatbot component.

image

I'll look into that, but I won't have time until after easter unfortunately.

EDIT: You're right. It should have a useEffect that updates the internal state. I'm planning to do a major rewrite after easter.

naman-gupta99 commented 3 years ago

Okay thank you!!!

FredrikOseberg commented 3 years ago

Okay thank you!!!

No problem. Could you try something for me?

Add this to the Chatbot.jsx file in node_modules:

useEffect(() => {
    setState(prev => ({ ...prev, ...config.state }))
}, [config.state])

Does that update your state internally when it re-renders?

naman-gupta99 commented 3 years ago

Will I have to build the package again?

Edit 1: I haven't ever made changes to node-modules. I tried looking up a few resources to how to do that. I tried it but it is showing the following error:

image

OnlineSmileDev commented 3 years ago

@FredrikOseberg How are you? Can you let me know how to use the validator? For example, the user should not be able to chat unless all the prompts are answered properly. But currently version, the user can send a message without selecting a prompt.

What do I do? Screen Shot 2021-04-12 at 10 54 10 PM