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

    Outsourcing – talent on demand
    • Services
    • Trends

    Outsourcing – talent on demand

    November 27, 2023 by createIT
    Digital marketing – transform data into insight 
    • Trends

    Digital marketing – transform data into insight 

    November 24, 2023 by createIT
    A simple JavaScript typewriter effect tutorial
    • Dev Tips and Tricks

    A simple JavaScript typewriter effect tutorial

    November 22, 2023 by createIT
    WP-HistographAI: reviving history with AI on WordPress
    • Dev Tips and Tricks

    WP-HistographAI: reviving history with AI on WordPress

    November 21, 2023 by createIT
    Update Excel files on OneDrive with Node.js, MS Graph
    • Dev Tips and Tricks

    Update Excel files on OneDrive with Node.js, MS Graph

    November 20, 2023 by createIT
    Popup Visits Plugin: engage your visitors on their X visit!
    • Dev Tips and Tricks
    • Technology

    Popup Visits Plugin: engage your visitors on their X visit!

    November 17, 2023 by createIT
    The most popular eCommerce technologies among top players
    • Technology
    • Trends

    The most popular eCommerce technologies among top players

    October 26, 2023 by createIT
    BaseLinker: the tool, challenges and BaseLinker alternatives
    • Technology
    • Trends

    BaseLinker: the tool, challenges and BaseLinker alternatives

    October 25, 2023 by createIT
    The power of popups: why every WordPress site needs one
    • Technology
    • Trends

    The power of popups: why every WordPress site needs one

    October 24, 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