Estoy tratando de evitar una lista de objetos que tengan un valor de '{}'
import { IRootState } from 'app/shared/reducers'; import { getEntity } from './determination.reducer'; import { IDetermination } from 'app/shared/model/tpa/determination.model'; import React, { lazy, useEffect } from 'react'; import { connect } from 'react-redux'; import { Link, RouteComponentProps } from 'react-router-dom'; export interface IDeterminationDetailProps extends StateProps, DispatchProps, RouteComponentProps<{ id: string }> {} export const DeterminationDetail = (props: IDeterminationDetailProps) => { useEffect(() => { props.getEntity(props.match.params.id); }, []); function waitForElementProps(){ if(props != null && props){ console.log('finished loading props.. ' + props.determinationEntity) } else { setTimeout(waitForElementProps, 5000); } } waitForElementProps(); var {determinationEntity} = props; const obj = JSON.stringify(determinationEntity); if(obj === '{}') { console.log('caught') waitForElementProps(); } if(!obj || obj==null || obj ==='{}'){ waitForElementProps(); } waitForElementProps(); console.log('new ' + obj);En la salida de la consola obtengo
finished loading props.. [object Object] caught finished loading props.. [object Object] new {} determination/FETCH_DETERMINATION_FULFILLED finished loading props.. [object Object] 2 new {"determination":{"id":1051,"a ... }¿Cómo es posible que mi código asigne el valor de '{}' a 'obj' a pesar de que estoy llamando a una función recursiva antes de que pueda llegar allí?
Este problema se relaciona con mi deseo de esperar a que lleguen los datos antes de analizarlos, porque sigo teniendo el problema de 'obj no está definido' cada vez que intento analizarlos.
Sé que hay una espera asíncrona en javascript donde puedo esperar a que finalice 'FETCH_DETERMINATION_FULFILLED', pero no sé cómo implementarlo. Aquí está mi llamada api (de una clase separada)
export const getEntities: ICrudGetAllAction<IDetermination> = (page, size, sort) => { const requestUrl = `${apiUrl}${sort ? `?page=${page}&size=${size}&sort=${sort}` : ''}`; return { type: ACTION_TYPES.FETCH_DETERMINATION_LIST, payload: axios.get<IDetermination>(`${requestUrl}${sort ? '&' : '?'}cacheBuster=${new Date().getTime()}`), }; };React (y Javascript) es esencialmente asíncrono. No es posible bloquear la espera de que se complete una operación asíncrona. Incluso async/await en realidad no bloquea, es solo azúcar sintáctico para cadenas de .then .
La forma de reaccionar para manejar esto sería hacer cumplir que el componente principal siempre pasa los accesorios que desea, o null cuando los accesorios no están poblados para que no se represente nada en el DOM hasta que haya cargado sus datos. Al igual que:
if (!props.determinationEntity) { return null; }Algunas otras notas:
No es posible que el parámetro props sea nulo. Si no se pasan accesorios, React pasa un objeto vacío.
if (props != null && props) es redundante, null es falso en Javascript, por lo que es equivalente a if (props)
En breve,
asíncrono/espera
Idealmente, esperaría la respuesta de la API en el enlace useEffect que implementó. Esto significa que el código ESPERARÁ a que la API responda antes de pasar a la siguiente línea del gancho useEffect. Luego puede guardar el valor de la respuesta en un objeto de estado para usarlo más tarde. Eso podría parecer algo tan fácil como esto:
useEffect(() => { const getData = async () => { const res = await props.getEntity(props.match.params.id); const resData = await res.json(); // now save to state setData(resData); // or parse as you need (as example) setName(resData?.details?.name); } getData(); }, []);agregar verificación nula
A partir del código que proporcionó, es difícil saber cómo se guardan los valores de la API actualmente en la variable props.determinationEntity . No importa cómo ocurra esta actualización, sin embargo, debe aplicar la verificación cuando esté usando el valor en su código más adelante para que no obtenga errores de tipo. Utilice el encadenamiento opcional , la fusión nula y el retorno simple if(!props.determinationEntity) return; ; declaraciones.
setTimeout no bloquea hilos
Con respecto a lo que dijiste:
¿Cómo es posible que mi código asigne el valor de '{}' a 'obj' a pesar de que estoy llamando a una función recursiva antes de que pueda llegar allí?
Invocar setTimeout dentro de la función waitForElementProps no bloqueará toda la continuación del código. El tiempo de espera se guardará y la ejecución del código continuará a través de la pila, llegando a la declaración de obj y estableciéndola en la cadena de un objeto vacío.
También tenga cuidado con var por una razón similar. Elevará la declaración para que tenga un alcance de función en lugar de un alcance de bloque como let y const , por lo que es posible que pueda acceder a las variables en lugares en los que "no debería" estar (dependiendo de lo que esté esperando).
Terminé implementando una solución barata para esto
aquí está el código que agregué
import testData from 'app/shared/testdata/determination.json'; var obj = testDataEsencialmente, todo lo que hice fue asignarle un valor predeterminado que era la estructura exacta de los datos que espera ('testData' es JSON en el mismo formato que 'obj'). Y para evitar cualquier posibilidad, incluso agregué una declaración 'if' más antes de renderizar.
if(obj=== undefined || obj = '{}'){ obj=testData; waitForElementProps; }