skip to Main Content

So I have a chat app where I can access different chat rooms. When I’m in one of the chat rooms, I can change chat rooms by clicking on the other chat rooms (just like how WhatsApp and other chat apps behaves). So I have a function which handles clicking on the other chat room as such:

const handleChatClick = () => {
   closeAllDocks(dispatch);
   history.push(`/chats/${chat.id}`);
};

So in my app, I have something called "Docks". For example, I can open the chat room profile page, and it’ll be opened as a "Dock" on the right side (split screen). So when I want to change chat room, I want to make sure that all of these docks are closed. This is where the closeAllDocks(dispatch) function comes in. In this case, dispatch is basically const dispatch = useDispatch() from redux. So when this gets called, all the docks’ state will be set to false.

However, the issue is that, when I run this function, the history.push(...) will get executed, and the closeAllDocks(dispatch) as well, but I guess history.push(...) will finish executing first. This causes some sort of delay, where I can see the content of the dock gets changed according to the new chat room (even though it’s only for a split second) then closes.

How should I be handling this?

2

Answers


  1. A trick/hack I’ve had to use in the past to solve issues similar to this is to place the navigation action in a short timeout so it’s placed at the end of Javascript’s event loop and allows the dispatched actions to process and React to rerender once then the navigation can be effected.

    Example:

    const handleChatClick = () => {
      closeAllDocks(dispatch);
      setTimeout(() => history.push(`/chats/${chat.id}`), 0);
      // or setTimeout(history.push, 0, `/chats/${chat.id}`);
    };
    

    An alternative might be to make your "close all docks" action/logic asynchronous, e.g. a createAsyncThunk, so you can await it in the UI code.

    Example:

    const closeAllDocks => dispatch => dispatch(closeAllDocksAsyncAction());
    
    const handleChatClick = async () => {
      await closeAllDocks(dispatch);
      history.push(`/chats/${chat.id}`);
    };
    
    Login or Signup to reply.
  2. history.push(…) will finish executing first.

    that is because history.push(...) is a synchronize code. sync code passed to main execution stack first to be executed. since the javascript is single-threaded, async code is passed to the event loop and the event loop continuously checks if the execution stack is empty or not. to wait for the async code promise to be resolved we use await

    const handleChatClick = async () => {
      await closeAllDocks(dispatch);  
      history.push(`/chats/${chat.id}`);
    };
    

    the await keyword is used to wait for a promise to resolve before moving on to the next line of code. It is often used with asynchronous functions to make them behave more like synchronous code.

    you can also use the .then() and .catch() methods with promises to handle asynchronous operations.

    const handleChatClick = () => {
      closeAllDocks(dispatch)
        .then(() => {
          history.push(`/chats/${chat.id}`);
        })
        .catch((error) => {
          console.error("An error occurred:", error);
        });
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search