Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why does storing a timeout in React context not work?

In my root component I have a context for keeping track of an API key that expires every once in a while:

function App() {
    const [apiKey, setApiKey] = useState("");
    const [timeout, setTimeout] = useState(null);
    const apiKeyContextValue = {
        apiKey,
        setKey: setApiKey,
        timeout,
        setTimeout
    };
    return (
            <apiKeyContext.Provider value={apiKeyContextValue}>
                     <ApiKeyForm/>
            </apiKeyContext.Provider>
    );

I set the api key from ApiKeyForm, where the user just inputs an API key; however, I also want to set a timeout that’ll reset apiKeyContextValue.apiKey once it expires:

const ApiKeyForm = ()=>{
    const apiKeyContext = useContext(ApiKeyContext);
    const handleSubmit = e => {
        //sets api key = to value in form input  
        apiKeyContext.setKey(e.target[0].value);

        //dummy debug code for now
        apiKeyContext.setTimeout(()=>{
            alert('should wipe api key now');
        }, 1000) 
        
    }
    return (<form onSubmit={handleSubmit}>
                ...
            </form>)
}

My issue is that when I submit my form, I get the alert from setTimeout immediately. Why is this and how would I fix this?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

Your setTimeout identifier taken from context is a state setter, not the standard window.setTimeout function. When you pass a function to a state setter, you’re using the callback form of the state setter, which will pass the most up-to-date value in state as the argument – for example

setSomeStateValue(mostUpToDateStateValue => {
  // code that relies on mostUpToDateStateValue

Which will run immediately. The same is going on with your code, only with different variable names.

Having a timeout and setTimeout in context state doesn’t seem to be helping you any here. If you just wanted to set the state to a timeout ID that can have clearTimeout called on it later, do:

const [timeoutId, setTimeoutId] = useState(null);

pass it down, and then do

apiKeyContext.setTimeoutId( // this references the state setter from context
    setTimeout(() => { // this references window.setTimeout
        alert('should wipe api key now');
    }, 1000)
);

If you don’t actually need to store the timeout ID in context, then you can remove it entirely and do, in ApiKeyForm:

setTimeout(() => { // this references window.setTimeout
    alert('should wipe api key now');
}, 1000)
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading