Instantiating the Client

Last Edit: Jan 22 2021

In every client-side integration, it will be necessary to open a WebSocket connection between the client device (cell phone/laptop/tablet, etc.) and the API using the connectUser(); (or SDK equivalent) method. Let's look at what the connectUser method is doing.

This method performs multiple functions:

  • The primary purpose of this method is to open a WebSocket connection. Thus, it should only be used once per session per user. Opening multiple WebSockets per user opens your application to a myriad of problems, including performance, billing, and unexpected behavior.

  • It Gets or Creates a new user. It will increase your MAU (monthly active users), Concurrent Connections (as long as the WebSocket is active), and is not a valid method for importing users.

  • It partially updates the user. Any key:value data fields passed in addition to the user_id are added or updated in the case that they already exist.

  • It should never be used server-side. Some SDK’s that can be used both server-side and client-side (JS SDK) expose this method in both places, so this is possible and strongly discouraged.

  • The WebSocket can be closed using client.disconnect(); (or language SDK equivalent).

  • The API response from this method contains useful information (more of this later).

Examples

Here's how you might use the connectUser method correctly


// ✅ You should disconnect once you are done with chatClient
const [ chatClient, setChatClient ] = useState(null);
const [ currentUser, setCurrentUser ] = useState(null);
useEffect(() => {
    const initChat = async () => {
        const client = new StreamChat('api_key', 'secret');
        const result = await chatClient.connectUser({ id: currentUser });
        setChatClient(client);
    }

    initChat();
    // .. and some more code here

    // This is correct teardown logic to ensure the WebSocket connection does not remain open once the component is 
    unmounted or initChat is called again.
    return () => {
        chatClient.disconnect();
    }
}, [currentUser])
                    

Here's an example of how an integration could overuse the connectUser function, creating far more concurrent connections than is required to accomplish the desired behavior. (This can result in driving up your bill, stability issues, or even just unexpected behavior when interacting with multiple open WebSockets)


// ❌ This will keep on creating new websocket connection
// everytime useEffect hook gets executed (on chances to `currentUser`)
const [ chatClient, setChatClient ] = useState(null);
const [ currentUser, setCurrentUser ] = useState(null);
useEffect(() => {
    const initChat = async () => {
        const client = new StreamChat('api_key', 'secret');
        const result = await chatClient.connectUser({ id: currentUser });
        setChatClient(client);
    }

    initChat();
    // .. and some more code here
}, [currentUser])