Get a free advice now!

    Pick the topic

    Developer OutsourcingWeb developingApp developingDigital MarketingeCommerce systemseEntertainment systems

    Thank you for your message. It has been sent.

    Tags

    Sendbird chat customization in React

    Sendbird chat customization in React

    Sendbird’s chat, APIs and SDKs are used by developers to build chat functionality. If you’re building a chat in your app or chatbot that will answer questions in an ecommerce shop, Sendbird provides tools to make it happen.

    Basic Chat in React

    Let’s start with something really simple, using the built-in UIKit features. The implementation here is simple, but the chat itself is quite advanced: Message threading, channel list, typing indicator, emoticons reactions, copy/edit/delete message, leaving chat, creating a new group chat, editing channel information meta-data, delivered message icon or sending a file, adding buttons.

    The first step will be to install the npm package:

    npm install sendbird-uikit

    The main app source code:

    // App.jsx
    import React from 'react';
    import './App.css';
    import { App as SendBirdApp } from "sendbird-uikit";
    import "sendbird-uikit/dist/index.css";
    const App = () => {
      return (
          <div className="App" style={{"height":"100%"}}>
            <SendBirdApp
                appId="XXX"
                userId="YYY"
            />
          </div>
      );
    };
    export default App;

    Make sure to provide a real appId and userId. Without them, the chat wouldn’t be able to connect to SendBird API. The last step will be to make chat 100% browser height:

    body, html, #root {
      height:100%;
    }

    That’s it, we now have a fully functional chat with a lot of interesting features!

    Customize or not?

    SendBird UIKit provides an option to customize the rendering of basic elements. In a situation when a custom view needs to be prepared, it is really handy. One thing that is worth mentioning is that the overwritten element will lose all the nice “default” features that are built-in.

    If you decide to overwrite the component, you will probably need to implement all those features by yourself. Sometimes, it is better to use only CSS styles to apply a new design or color changes. In the case of more advanced changes, a component override will probably be needed.

    SB Chat Customization

    We’re going to create render views for the chat header, channel list, message thread and message input. The default components will be overwritten by our custom ones. We will have full control over what is happening inside the component and we can apply our HTML code structure. Make sure to change the APP_ID, USER_ID and CHANNEL_URL variables.

    // App.jsx
    import React from 'react';
    import './App.css';
    import {
        SendBirdProvider,
        Channel,
        ChannelList
    } from 'sendbird-uikit';
    import "sendbird-uikit/dist/index.css";
    import {MyCustomChatMessage} from "./MyCustomChatMessage";
    import CustomizedMessageInput from "./CustomizedMessageInput";
    import {CustomizedHeader} from "./CustomizedHeader";
    import {MyCustomChannelPreview} from "./ChannelPreview";
    const APP_ID = "AAA";
    const USER_ID = "BBB";
    const CHANNEL_URL = "CCC";
    const App = () => {
        return (
            <div style={{ height: '100vh' }} className={"mainWrapper"}>
                <SendBirdProvider
                    theme="light"
                    appId={APP_ID}
                    userId={USER_ID}
                >
                    <div className="sendbird-app__wrap">
                        <div className="sendbird-app__conversation-wrap">
                            <div>
                                <ChannelList renderChannelPreview={MyCustomChannelPreview}
                                     onChannelSelect={(channel) => { console.warn(channel); }}
                                />
                            </div>
                            <Channel
                                channelUrl={CHANNEL_URL}
                                renderChatItem={({ message, onDeleteMessage, onUpdateMessage }) => (
                                    <MyCustomChatMessage
                                        message={message}
                                        onDeleteMessage={onDeleteMessage}
                                        onUpdateMessage={onUpdateMessage}
                                    />
                                )}
                                renderMessageInput={({ channel, user, disabled }) => (
                                    <CustomizedMessageInput
                                        channel={channel}
                                        user={user}
                                    />
                                )}
                                renderChatHeader={({ channel, user }) => (
                                    <CustomizedHeader
                                        userId={user}
                                        channel={channel}
                                    />
                                )}
                            />
                        </div>
                    </div>
                </SendBirdProvider>
            </div>
        );
    };
    export default App;

    The custom view for messages:

    // MyCustomChatMessage.jsx
    import React from 'react';
    export const MyCustomChatMessage = (props) => {
        const { message, onDeleteMessage, onUpdateMessage } = props;
        console.log("rendering");
        return (
            <div className={(message.customType ? "type--" + message.customType : '')+ ' customizedMessage'}>
                <div className="customizedMessage_content">
                    { message.messageType === 'file'
                        ? (
                            <div className="img-fluid">
                                <img
                                    className="img-fluid"
                                    src={message.url}
                                    alt={message.name}
                                />
                            </div>
                        ) :
                        (
                            <>
                                {message.message}
                            </>
                        )
                    }
                </div>
                <div className="customizedMessage_author">
                    {` by 
                        ${message.messageType === 'admin'
                        ? 'Channel Admin'
                        : message.sender && message.sender.userId}
                    `}
                </div>
                <hr/>
            </div>
        );
    };

    The custom view for chat header:

    // CustomizedHeader.jsx
    import React, { useMemo } from "react";
    export const CustomizedHeader = (props) => {
        const { channel } = props;
        const channelName = channel.name;
        const channelAvatar = useMemo(() => {
            if (channel.coverUrl) {
                return <img src={channel.coverUrl} style={{width:'100px'}} />;
            }
            return (
                <></>
            );
        }, [channel]);
        const channelTitle = useMemo(() => {
            if (channelName) {
                return channelName;
            }
        }, [channelName]);
        return (
            <div className="customizedHeaderWrapper">
                <div>
                    {channelAvatar}
                </div>
                <div>
                    {channelTitle}
                </div>
            </div>
        );
    }

    The custom view for message text area and send message:

    // CustomizedMessageInput.jsx
    import React, { useState } from "react";
    import { sendBirdSelectors, withSendBird } from "sendbird-uikit";
    function CustomizedMessageInput(props) {
        // props
        const {
            channel,
            disabled,
            // from mapStoreToProps
            sendUserMessage,
            sendFileMessage,
            sdk,
        } = props;
        // state
        const [inputText, setInputText] = useState("");
        const [isShiftPressed, setIsShiftPressed] = useState(false);
        // event handler
        const handleChange = event => {
            setInputText(event.target.value);
        };
        const KeyCode = {
            SHIFT: 16,
            ENTER: 13,
        };
        const sendUserMessage_ = event => {
            if(!inputText){
                return;
            }
            const params = new sdk.UserMessageParams();
            params.message = inputText;
            sendUserMessage(channel.url, params)
                .then(message => {
                    console.log(message);
                    setInputText("");
                })
                .catch(error => {
                    console.log(error.message);
                });
        };
        return (
            <div className="customized-message-input">
                <div id="customized-message-input-wrapper">
                    <textarea
                        id="customized-message-input"
                        type="txt"
                        value={inputText}
                        onChange={handleChange}
                        onKeyDown={(e) => {
                            if (e.keyCode === KeyCode.SHIFT) {
                                setIsShiftPressed(true);
                            }
                            if (!isShiftPressed && e.keyCode === KeyCode.ENTER) {
                                e.preventDefault();
                                sendUserMessage_();
                            }
                        }}
                        onKeyUp={(e) => {
                            if (e.keyCode === KeyCode.SHIFT) {
                                setIsShiftPressed(false);
                            }
                        }}
                    />
                    <button
                        onClick={sendUserMessage_}
                    >
                       Send message
                    </button>
                </div>
            </div>
        );
    }
    const mapStoreToProps = store => {
        const sendUserMessage = sendBirdSelectors.getSendUserMessage(store);
        const sdk = sendBirdSelectors.getSdk(store);
        const sendFileMessage = sendBirdSelectors.getSendFileMessage(store);
        return {
            sendUserMessage,
            sdk,
            sendFileMessage
        };
    };
    export default withSendBird(CustomizedMessageInput, mapStoreToProps);

    And finally, the channel list customization:

    // ChannelPreview.jsx
    export const MyCustomChannelPreview = ({ channel, onLeaveChannel }) => {
        return  (
            <div style={{ border: '1px solid gray' }}>
                <h3>{channel.name}</h3>
                <img height="20px" width="20px" src={channel.coverUrl} />
                <button onClick={() => {
                    const callback = () => {
                        console.warn('Leave channel success')
                    };
                    onLeaveChannel(channel, callback);
                }}
                > Leave
                </button>
            </div>
        )
    } ;

    Customized chat demo

    Now we have the ability to apply a custom HTML structure and advanced changes to SendBird chat elements. Without styles, the chat looks really raw, but functionality works fine. What is left is styling, but this is beyond the scope of this article.

    Comments
    0 response

    Add comment

    Your email address will not be published. Required fields are marked *

    Popular news

    eCommerce growth – is your business ready?
    • Services
    • Trends

    eCommerce growth – is your business ready?

    April 8, 2024 by createIT
    Digital marketing without third-party cookies – new rules
    • Technology
    • Trends

    Digital marketing without third-party cookies – new rules

    February 21, 2024 by createIT
    eCommerce healthcheck
    • Services
    • Trends

    eCommerce healthcheck

    January 24, 2024 by createIT
    Live Visitor Count in WooCommerce with SSE
    • Dev Tips and Tricks

    Live Visitor Count in WooCommerce with SSE

    December 12, 2023 by createIT
    Calculate shipping costs programmatically in WooCommerce
    • Dev Tips and Tricks

    Calculate shipping costs programmatically in WooCommerce

    December 11, 2023 by createIT
    Designing a cookie consent modal certified by TCF IAB
    • Dev Tips and Tricks

    Designing a cookie consent modal certified by TCF IAB

    December 7, 2023 by createIT
    Understanding the IAB’s Global Vendor List (GVL)
    • Dev Tips and Tricks

    Understanding the IAB’s Global Vendor List (GVL)

    December 6, 2023 by createIT

    Support – Tips and Tricks
    All tips in one place, and the database keeps growing. Stay up to date and optimize your work!

    Contact us