• Jobs
  • About Us
  • professionals
    • Home
    • Jobs
    • Courses and challenges
  • business
    • Home
    • Post vacancy
    • Our process
    • Pricing
    • Assessments
    • Payroll
    • Blog
    • Sales
    • Salary Calculator

0

100
Views
The useReducer is not updating the state value

Hiho!

I thought it would be cool for my page to have a 100% covering black transparent overlay with text when its waiting for data from the server. So it its waiting for data a 30% black overlay with the text "Loading ...". I wrote the context and provider and while it works it is a bit too fast :-). I want it to hide the overlay with a delay for 1500s (or less), so I tried changing the useState to a useReducer and implement the logic in setDisplayStateFunc:

import { createContext, useReducer, useState } from "react";

function useOverlay(display) {

    async function setDisplayStateFunc(state, action) {

        await new Promise(resolve => setTimeout(resolve, 1500));
        console.log(`returning: ${action}`);
        return action;
    }

    const [displayState, setDisplayState] 
        //= useState(display);
        = useReducer(setDisplayStateFunc, display);

    return { displayState, setDisplayState }
}

const OverlayContext = createContext();

function LoaderOverlay({ children, display = 'block' }) {

    const { displayState, setDisplayState } = useOverlay(display);

    return (
        <OverlayContext.Provider value={{ displayState, setDisplayState }}>
            <div className="loader" style={{ "display": displayState }}>
                <span>Loading ...</span>
            </div>

            {children}
        </OverlayContext.Provider>
    )
}

export { LoaderOverlay, OverlayContext };

The console.log I have there is outputting the right values, and out and about in my componets i use it by setting up useContext and then setDisplayState('none') after I'm done loading.

It works with useState, but I want a small delay. Where did I go wrong?

almost 3 years ago · Santiago Gelvez
1 answers
Answer question

0

I don't think useReducer support async function. The notion of side effect should generally not be inside the reducer.

I would suggest using a useEffect to handle this inside of LoaderOverlay

import { createContext, useReducer, useState } from "react";

function useOverlay(display) {

    async function setDisplayStateFunc(state, action) {
        return action;
    }

    const [displayState, setDisplayState]
        = useReducer(setDisplayStateFunc, display);

    return { displayState, setDisplayState }
}

const OverlayContext = createContext();

function LoaderOverlay({ children, display = 'block' }) {

    const { displayState, setDisplayState } = useOverlay();

    useEffect(() => {
    async function waitSomeTime() {
      await new Promise(resolve => setTimeout(resolve, 1500));
      setDisplayState()
    }
    waitSomeTime()
    }, [setDisplayState])

    return (
        <OverlayContext.Provider value={{ displayState, setDisplayState }}>
            <div className="loader" style={{ "display": displayState }}>
                <span>Loading ...</span>
            </div>

            {children}
        </OverlayContext.Provider>
    )
}

export { LoaderOverlay, OverlayContext };

almost 3 years ago · Santiago Gelvez Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Our process Sales
Legal
Terms and conditions Privacy policy
© 2025 PeakU Inc. All Rights Reserved.

Andres GPT

Recommend me some offers
I have an error