es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Llamadas infinitas a la API al cambiar el estado en el callback.

Estoy intentando cargar datos desde una API en un treeview (Material-UI). Si los datos son estáticos, entonces todo está bien, pero si uso la API en una devolución de llamada, desencadena llamadas ilimitadas…

const getTreeItemsFromData = (treeItems) => {
  //e.stoppropagation();
  return treeItems.map((treeItemData) => {
    let children = undefined;
    if (treeItemData.children && treeItemData.children.length > 0) {
      children = getTreeItemsFromData(treeItemData.children);
    }
    return (
      <treeitem key="{treeItemData.id}" nodeid="{treeItemData.id}" label="{treeItemData.name}" children="{children}"></treeitem>
    );
  });
};

export default function UpdateFieldObservations({
  formdata,
  handleChangeParent
}) {
  const [matrixData, setMarixData] = useState([]);

  const airdata = [
    {
      id: 1,
      name: "Soil Vapour",
      children: [
        {
          id: 11,
          name: "Grab Sample"
        },
        {
          id: 12,
          name: "Insitu Meter Reading"
        }
      ]
    }
  ];

  console.log("Call API with matrixId : " + form.matrixId);
  axiosInstance
    .get("/observations/" + form.matrixId, {
      headers: { "Content-Type": "application/json" }
    })
    .then((res) => {
      console.log(res);
    })
    .catch((err) => {
      console.log("Error: " + err);
    });

  return (
    <>
      <treeview classname="{classes.root}" defaultcollapseicon=""></treeview><expandmoreicon></expandmoreicon>}
        defaultExpandIcon={<chevronrighticon></chevronrighticon>}
        onNodeSelect={handleNodeSelected}
      >
        {getTreeItemsFromData(airdata)}


  );
}

Ahora, si agrego debajo

console.log(res);
setMarixData(res);

Comienza con llamadas ilimitadas a la API… ¿Qué estoy haciendo mal y cómo cargar mejor estos datos en el árbol en lugar de airdata?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    El problema con el código es que se llama a axiosInstance.get(...) cada vez que se renderiza el componente UpdateFieldObservations. Para evitar esto, puedes usar el hook useEffect para cargar los datos solo una vez cuando se monta el componente.

    Así es como puedes modificar el código para obtener datos de la API y establecerlos en la variable de estado matrixData:

    export default function UpdateFieldObservations({
      formdata,
      handleChangeParent
    }) {
      const [matrixData, setMatrixData] = useState([]);
    
      useEffect(() => {
        console.log("Llamar API con matrixId: ", form.matrixId);
        axiosInstance
          .get("/observations/" + form.matrixId, {
            headers: { "Content-Type": "application/json" }
          })
          .then(res => {
            setMatrixData(res.data); // establecer los datos obtenidos en el estado
          })
          .catch(err => {
            console.log("Error: ", err);
          });
      }, []); // llamar al efecto solo una vez cuando se monta el componente
    
      const handleNodeSelected = nodeId => {
        // manejar el evento de selección de nodo aquí
      };
    
      const getTreeItemsFromData = treeItems => {
        return treeItems.map(treeItemData => {
          let children = undefined;
          if (treeItemData.children && treeItemData.children.length > 0) {
            children = getTreeItemsFromData(treeItemData.children);
          }
          return (
            <treeitem key="{treeItemData.id}" nodeid="{treeItemData.id}" label="{treeItemData.name}" children="{children}"></treeitem>
          );
        });
      };
    
      return (
        <>
          <treeview classname="{classes.root}" defaultcollapseicon=""></treeview><expandmoreicon></expandmoreicon>}
            defaultExpandIcon={<chevronrighticon></chevronrighticon>}
            onNodeSelect={handleNodeSelected}
          >
            {/* utiliza los datos obtenidos de la API en lugar de airdata */}
            {getTreeItemsFromData(matrixData)}
    
    
      );
    }
    

    También puedes agregar una variable de estado de carga para mostrar un spinner o un mensaje mientras se obtienen los datos. ¡Espero que esto ayude!

Comments are closed.