0

I have an asynchronous function running in my web application that enables a chat input. In a different component I need to set a variable to the input and then focus() on it when certain conditionals are met. Unfortunately the chat input DOM element isn't always available when I try to declare it based on the asynchronous nature of the function that enables it. Being familiar with how setTimeoout() works with the call stack I wrapped my declaration in a setTimeout and everything (seemingly) works as expected now.

So my question is if this is a good practice or not? I'm using React/Redux and will have to do a lot of prop threading and extra logic to get a seemingly easy task accomplished without the setTimeout.

Mark
  • 1,610
  • 1
  • 14
  • 27
  • 1
    Sounds like you should be using promises – DavidB Mar 04 '19 at 16:47
  • My component I'm using this in has no idea that the function to set the input to enabled is being ran. I could use a promise, but that would require setting up some redux actions and some prop threading to give my component access to this information. Which is why I'm asking if this is an okay practice. Ideally I would use a promise or async/await. It just seems like a lot of work for something very simple. – Mark Mar 04 '19 at 16:51
  • Using `setTimeout` to fix a timing issue when you waiting for some other parts to be ready is not a good idea. What if you change some parts of the code logic and it now take even longer until the element is available then your current delay for `setTimeout` might fail. So you need some way so that one part of the code can register itself to be notified when another part of the code is ready. That can be done with events, or might be done with Promises. How exactly depends on the exact use-case and current code design of your project. – t.niese Mar 04 '19 at 17:04
  • I didn't put any delay on the setTimeout. It's not hitting an API or anything, it just happens to be getting declared in the call stack before the chat input being enabled is. the setTimeout is just waiting for the call stack to be empty before setting the variable to the DOM element. – Mark Mar 04 '19 at 17:06
  • https://stackoverflow.com/questions/779379/why-is-settimeoutfn-0-sometimes-useful This is a good explanation of what I'm trying to accomplish with my logic. – Mark Mar 04 '19 at 17:09

1 Answers1

0

It is an alright practice ;)

It gets the job done, but it is usually preferable to work with callbacks or promises instead of polling to see if the dom is ready. The main failing with a "setTimeout" approach is that you are setting a timer and what if the resource (chat plugin) takes longer to load than the timer you set.

// Run it
main();

// Supporting code
function main() {
    let attempts = 0;
    const maxAttempts = 10;
    tryUpdate();

    function tryUpdate() {
        // Call it once
        attempts++;
        const success = updateAndFocus();
        console.log(attempts);

        // Keep calling it every 100ms
        if (!success && attempts < maxAttempts) {
            setTimeout(() => tryUpdate(), 100);
        }
    }
}

function updateAndFocus() {
    const el = document.getElementById('findme');
    if (!el) return false;

    // do work
    el.focus;

    return true;
}
AKnox
  • 2,455
  • 3
  • 19
  • 19
  • Thanks for the code!! My chat plugin is already running and is just waiting for certain actions to happen to enable the chat input. In my case it's two (or one) elements on a calendar picker getting selected to re-enable the chat input. It's not fetching data from anywhere, or doing any heavy lifting. The input being enabled just ends up most of the time being called in the stack after I am trying to declare it. – Mark Mar 04 '19 at 17:44