Sendbird UIKit: subscribe for new messages for user?

Hi, how do I subscribe for new messages/channels for a user?
Got a custom chat list, with a last message preview (but data for this list goes from a custom API, which also attaches information about users from our DB). Need to maintain its state in real time. Re-fetching a full list wouldn’t be nice, I guess.

Docs are pretty poor on UIKit components, context, props etc. An example on that would be great.

UIKit v1.1.2

Thanks!

Hi @Dmytro

Apologies about the docs - we understand that docs are the most important part of any library - we are working on improving them. As a first step, we have made a bunch of examples on various use cases for UIKit. You can find them here

I recommend you to follow the pattern from https://github.com/sendbird/SendBird-JavaScript/tree/master/uikit-samples#2-5-customizing-messageinput

Using withSendBird HOC to access SDK to your custom component
And from there, use the SDK instance and use event handlers to listen to events


import React, { useEffect } from "react";
import { sendBirdSelectors, withSendBird } from "sendbird-uikit";

const CustomComponent = (props) => {
  const {sdk} = props;
  useEffect(() => {
    var ChannelHandler = new sb.ChannelHandler();
    ChannelHandler.onMessageReceived = function(channel, message) {
      // your custom logic
    };
    sb.addChannelHandler(UNIQUE_HANDLER_ID, ChannelHandler);
    return () => {
      // cleanup
      sb.removeChannelHandler(UNIQUE_HANDLER_ID);
    }
  }, [sdk])
  return (
    <div />
  )
}

const mapStoreToProps = store => {
  const sdk = sendBirdSelectors.getSdk(store);
  return {
    sdk,
  };
};

export default withSendBird(CustomComponent, mapStoreToProps);

^^ If this didnt help, please let me know

1 Like

Hi, thanks, checking this out.

How do I get chat list up-to-date in real time? Apply some filters? I think it’s better to use built-in SDK now, and request additional data (like on users data) when chat list is fetched first time or changed (messages, new channels).

Also, issue is to meet all requirements I fetch full chat list (have advanced search, pinned chats where pins are stored on our side — didn’t see if you have that feature now). And it complicates things a bit :slight_smile:

By chatlist you mean <ChannelList />? Or <Channel />?

(Edit - Your use case seems a bit complicated to discuss over a forum, in the meantime, I will see if I can get someone from sales/customer success to connect with you)

Yes, I meant channel list.

@Dmytro
This is Eric from solutions engineering team.

I would like to understand your use case better.
Could you share some example service (application/website) that provide the same experience you are trying to build in your system? (Screenshot or video would be the best)

If you don’t want to reveal your use case, you can send us a support cast via dashboard webform (https://dashboard.sendbird.com/settings/contact_us)

Thanks for this response, its helped me quite a bit. Where does the ‘sb’ instance come from in this case / are you able to grab it from the SendBirdProvider? I’m attempting to get out of chat notifications setup while using the sb UIKit package. Thanks!

1 Like

@ccarithe1

Where does the ‘sb’ instance come from in this case / are you able to grab it from the SendBirdProvider? ->

Yes, sb instance comes from SendBirdProvider, you can access it through withSendBird HOC and some of our selectors

Find an example here - https://codesandbox.io/s/2-5-customizing-chatinput-wgi9d?file=/src/CustomizedMessageInput.js:3897-3967

For more samples, visit https://github.com/sendbird/SendBird-JavaScript/tree/master/uikit-samples

Also, I think, your use case is a nice idea for our next example :+1:

2 Likes

@Dmytro Just following on your question. Did you get this part implemented as you wished?

Ahh I think this may actually have just been a typo in the example I ran into the same issue when testing it out. Think it is meant to be sdk which is the Sendbird instance instead of sb. So that would update Sravan’s example the this:

import React, { useEffect } from "react";
import { sendBirdSelectors, withSendBird } from "sendbird-uikit";

const CustomComponent = (props) => {
  const {sdk} = props;
  useEffect(() => {
    var ChannelHandler = new sb.ChannelHandler();
    ChannelHandler.onMessageReceived = function(channel, message) {
      // your custom logic
    };
    sdk.addChannelHandler(UNIQUE_HANDLER_ID, ChannelHandler);
    return () => {
      // cleanup
      sdk.removeChannelHandler(UNIQUE_HANDLER_ID);
    }
  }, [sdk])
  return (
    <div />
  )
}

const mapStoreToProps = store => {
  const sdk = sendBirdSelectors.getSdk(store);
  return {
    sdk,
  };
};

export default withSendBird(CustomComponent, mapStoreToProps);

Hey Alex, any more details on this? Using your code example above I’m still getting thrown ‘sb’ is not defined (from the line: var ChannelHandler = new sb.ChannelHandler()).

Replacing sb with sdk in this line (var ChannelHandler = new sdk.ChannelHandler()) throws a TypeError: sdk.ChannelHandler is not a constructor.

Thanks.

Edit: I spoke too soon. Found your example (https://github.com/AlexOrrSB/sendbird-multitab-demo) which has got it all. Thanks!

1 Like

On line 7, is new sb.ChannelHandler() supposed to be changed to new sdk.ChannelHandler()? And once you import this component into another file, what’s the syntax to use it? I went through the repo linked to in the previous post and ended up with syntax errors following its convention.

This is the error that appears when running the above component:

# Unhandled Runtime Error

TypeError: Cannot read property 'stores' of undefined

The line that gets pointed to for the error is const sdk = sendBirdSelectors.getSdk(store);

We support using a hook to access the SDK instance if you don’t want to wrap your component with an HOC. It still needs to be used in a component that is within the provider. Here’s an example that shows that in action.

EDIT:
This is a simpler approach and I didn’t realize that repo was still visible after being archived, it is a bit outdated. I am going to remove the multitab demo repo and instead we recommend you follow the code sandbox example.

1 Like

Thanks, this approach is easier to read. Here’s what I have based on this approach:

import React, { useEffect } from "react";
import { useSendbirdStateContext, sendBirdSelectors } from "sendbird-uikit";

function SendbirdNotificationObject() {
  const context = useSendbirdStateContext();
  console.log(context);
  const sdkInstance = sendBirdSelectors.getSdk(context);
  useEffect(() => {
    if (sdkInstance && sdkInstance.ChannelHandler) {
      const channelHandler = new sdkInstance.ChannelHandler();
      channelHandler.onMessageReceived = (channel, message) => {
        console.log(channel);
        console.log(message);
      };
      sdkInstance.addChannelHandler('GLOBAL_HANDLER', channelHandler);
    }

    return () => {
      if (sdkInstance && sdkInstance.removeChannelHandler) {
        sdkInstance.removeChannelHandler('GLOBAL_HANDLER');
      }
    };
  }, [sdkInstance]);
  return (
    <></>
  );
}

export default SendbirdNotificationObject;

I am getting this error that traces itself to the UIKit component:

It seems like const context = useSendbirdStateContext() on line number 5 is returning undefined - which results in the undefined context variable being provided to sendBirdSelectors.getSdk() on line 7.

Any idea why what might be behind this?

Can you share with us where SendbirdNotificationObject is wrapped by the provider?

So something like this:

    import { SendBirdProvider, withSendBird, ChannelList, ChannelSettings, Channel, App as SendBirdApp } from "sendbird-uikit";
    import SendbirdNotificationObject from "./SendbirdNotificationObject";

    .....

   <div>
       <SendbirdNotificationObject/>
   </div>

Hey @diggtydo,

It would be beneficial to see more context that what is provided. We’d like to see where the SendBirdProvider Wrapper is in relation to the SedbirdNotificationObject component.

This example is based on the sample Alex posted last week. He explicitly said this is the non-HOC way of doing it

If you take a look at the codesandbox that Alex posted, you’ll see that we anticipate your SendbirdNotificationObject component to be inside of a component that is wrapped by SendbirdProvider

Here is the code pulled from the linked codesandbox (removing the parts that are not relevant to you):

App.js

import React from "react";
import { SendBirdProvider as SBProvider } from "sendbird-uikit";
import { APP_ID, USER_ID, NICKNAME } from "./const";
import CustomizedApp from "./CustomizedApp";

export default function App() {
  return (
    <div className="app-wrapper">
      <SBProvider appId={APP_ID} userId={USER_ID} nickname={NICKNAME}>
        <CustomizedApp />
      </SBProvider>
    </div>
  );
}

CustomizedApp.js

import React, { useState } from "react";
import {
  Channel as SBConversation,
  ChannelList as SBChannelList,
  ChannelSettings as SBChannelSettings
} from "sendbird-uikit";
import SendbirdNotificationObject from './SendbirdNotificationObject'

function CustomizedApp(props) {
...
    <SendbirdNotificationObject />
...
}
2 Likes