¡Hi Ho!
Pensé que sería genial que mi página tuviera una superposición transparente negra que cubriera el 100 % con texto cuando esté esperando datos del servidor. Por lo tanto, está esperando datos, una superposición negra del 30 % con el texto "Cargando...". Escribí el contexto y el proveedor y, aunque funciona, es demasiado rápido :-). Quiero que oculte la superposición con un retraso de 1500 s (o menos), así que intenté cambiar useState a useReducer e implementar la lógica en 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 };
El console.log
que tengo allí está generando los valores correctos, y en mis componentes lo uso configurando useContext
y luego setDisplayState('none')
después de que termine de cargar.
Funciona con useState, pero quiero un pequeño retraso. ¿Qué hice mal?
No creo que useReducer
admita la función async
. La noción de efecto secundario generalmente no debe estar dentro del reductor.
Sugeriría usar un useEffect para manejar esto dentro de 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 };