Search code examples
javascriptreactjsfetch

*any fuction* "is not a function" Reactjs fetch


i've tried to make a fetch and take one element of the data base by id on Reactjs, backend with javascript(node + express + sequelize), but i had some problems and i couldn't at anytime. im searched on google but i dont know hot to apply the solutions on my code... here some examples of my trying:

import { useState } from "react";
import { useParams, Link } from "react-router-dom";

import "./detallesBarrio.css";

const BarriosDetails = () => {
  const { id } = useParams();
  const [barrio, setBarrio] = useState({});

  const loadBarrioDetails = () => {
    fetch("http://localhost:3001/api/barrios")
      .then((x) => x.json())
      .then((y) => y.data)
    //   .then((z) => console.log(z))
      .then((allBarrio) => setBarrio(allBarrio));
  };
  
let byid = barrio.filter(obj => {
    return obj.id === id;
});
 console.log(byid);

  loadBarrioDetails();

  return (
    <main className="barrio-details">
      {byid.map(obj => {
        return (
          <div key={obj.id}>
            <div>
              <h1>Detalles de {obj.nombre}</h1>
              <img src={obj.foto} alt="imagen no disponible" />

              <article>
                <Link to="/barrios">Volver</Link>
              </article>
            </div>
          </div>
        );
      })}
    </main>
  );
};

export default BarriosDetails;

also my tryings:

-no filter function (problem: map is not a function)

import { useState } from "react";
import { useParams, Link } from "react-router-dom";

import "./detallesBarrio.css";

const BarriosDetails = () => {
  const { id } = useParams();
  const [barrio, setBarrio] = useState({});

  const loadBarrioDetails = () => {
    fetch(`http://localhost:3001/api/barrios`)
      .then((x) => x.json())
      .then((y) => y.data)
    //   .then((z) => console.log(z))
      .then((allBarrio) => setBarrio(allBarrio));
  };

  loadBarrioDetails();

  return (
    <main className="barrio-details">
      {barrio.map((barri) => {
        return (
          <div key={barri.id}>
            <div>
              <h1>Detalles de {barri[id].nombre}</h1>
              <img src={barri[id].foto} alt="imagen no disponible" />

              <article>
                <Link to="/barrios">Volver</Link>
              </article>
            </div>
          </div>
        );
      })}
    </main>
  );
};

export default BarriosDetails;

-no maping (problem: the code dont recognise 'nombre'(database camp') on '{barrio[id].nombre}')

import { useState } from "react";
import { useParams, Link } from "react-router-dom";

import "./detallesBarrio.css";

const BarriosDetails = () => {
  const { id } = useParams();
  const [barrio, setBarrio] = useState({});

  const loadBarrioDetails = () => {
    fetch(`http://localhost:3001/api/barrios`)
      .then((x) => x.json())
      .then((y) => y.data)
      .then((z) => console.log(z))
      .then((allBarrio) => setBarrio(allBarrio));
  };

  loadBarrioDetails();

  return (
    <main className="barrio-details">
      <div>
        <h1>Detalles de {barrio[id].nombre}</h1>
        <img src={barrio[id].foto} alt="imagen no disponible" />

        <article>
          <Link to="/barrios">Volver</Link>
        </article>
      </div>
    </main>
  );
};

export default BarriosDetails;

yes console.log give me the correct array


Solution

    • You are getting map is not a function because you're initiating the state as an object. is should be useState([]) instead of useState({})
    • based on your code you want to filter by id and id is unique so it's better to use array.find(obj => obj.id === id) than using array.filter().
    • in your first snippet let byid = barrio.filter(obj => { return obj.id === id; }); is executed before running the fetch and loading data.

    try using useEffect for this kind of needs and loading data as a side effect after mounting the component and you should check the existance of an object or array before accessing it useEffect(() => loadBarrioDetails(), [])

    Or since you just need one single object you can use like this:

    import { useState } from "react";
    import { useParams, Link } from "react-router-dom";
    
    import "./detallesBarrio.css";
    
    const BarriosDetails = () => {
      const { id } = useParams();
      const [barrio, setBarrio] = useState(null);
    
      const loadBarrioDetails = () => {
        fetch(`http://localhost:3001/api/barrios`)
          .then((x) => x.json())
          .then((y) => y.data)
          .then((allBarrio) => {
            const byId = allBarrio.find(obj => obj === id);
            setBarrio(byId ?? null);
        });
      };
    
    useEffect(() => loadBarrioDetails(), []);
    
    
    if (!barrio) return <></> // anything to display that the data is loading or doesn't exist depends on you need.
      return (
        <main className="barrio-details">
          <div>
            <h1>Detalles de {barrio.nombre}</h1>
            <img src={barrio.foto} alt="imagen no disponible" />
    
            <article>
              <Link to="/barrios">Volver</Link>
            </article>
          </div>
        </main>
      );
    };
    
    export default BarriosDetails;