Estoy creando una nueva aplicación React, además de un modelo existente. Utiliza carga diferida, combinada con React.Suspense.
El problema es que, como en la mayoría de las aplicaciones React, necesito obtener algunos metadatos iniciales del servidor cada vez que se carga la aplicación. Llamémoslo "getAppMetaData".
Entonces, ¿cuál es el problema? El problema es que mientras getAppMetaData está pendiente, necesito presentar algún cargador/spinner. Y esto es exactamente lo que hace React.Suspense: muestra la interfaz de usuario "alternativa". Por supuesto, podría ejecutar un cargador separado (que en realidad puede ser el mismo que la interfaz de usuario alternativa), pero esto crea un problema de UX, donde la animación del cargador se "reinicia" entre los procedimientos.
Entonces, la pregunta es, ¿cómo puedo "integrar" otras acciones asíncronas en esta suspensión? En palabras simples: "Mi interfaz de usuario alternativa ya se muestra, mientras que el fragmento (de la carga diferida) está cargado, entonces, ¿cómo hago para que también espere getAppMetaData?"
Este es mi enrutador:
<ErrorBoundary> <Suspense fallback={<div className={styles.loader}><Loader /></div>}> <Switch> <ProtectedRoute exact component={Home} path="/"> </ProtectedRoute> <Route path="/lesson"> <Lesson></Lesson> </Route> <Route exact path="/login"> <Login /> </Route> <Route path="/about"> <About /> </Route> <Route path="*"> <NotFound /> </Route> </Switch> </Suspense> </ErrorBoundary>La documentación de React establece que la biblioteca de retransmisión debe usarse para esto, pero no quiero usar ninguna biblioteca especial para mis llamadas a la API, solo para superar este simple. También afirma:
¿Qué pasa si no uso el relé? Si no usa Relay hoy, es posible que tenga que esperar antes de poder probar Suspense en su aplicación. Hasta ahora, es la única implementación que probamos en producción y en la que confiamos.
Todo lo que necesito es integrar una pequeña llamada API inicial en este procedimiento. ¿Cómo puede hacerse esto? Cualquier sugerencia será muy apreciada.
Movería a los hijos de Suspense a un nuevo componente y leería los datos de este componente.
Los datos se cargarán mediante una función personalizada fetchData que creará la promesa y devolverá un objeto que contiene un método de read que lanzará la promesa si los datos no están listos.
function fetchData() { let status = 'pending'; let result; const promise = fetch('./data.json') .then(data => data.json()) .then(r => { status = 'success'; result = r; }) .catch(e => { status = 'error'; result = e; }); return { read() { if (status === 'pending') { throw promise; } else if (status === 'error') { throw result; } else if (status === 'success') { return result; } } }; } const dataWrapper = fetchData(); function AppBody() { const data = dataWrapper.read(); // you can now manipulate the data return ( <Switch> <ProtectedRoute exact component={Home} path="/"/> <Route path="/lesson" component={Lesson} /> <Route exact path="/login" component={Login} /> <Route path="/about" component={About} /> <Route path="*" component={NotFound} /> </Switch> ) } function App() { return ( <ErrorBoundary> <Suspense fallback={<div className={styles.loader}><Loader /></div>}> <AppBody/> </Suspense> </ErrorBoundary> ); }Aquí hay un ejemplo de stackblitz
Este código está inspirado en este codesandbox de la documentación de reacción .