Home > other >  Cannot read properties of undefined (reading 'map') in reactjs fetch
Cannot read properties of undefined (reading 'map') in reactjs fetch

Time:05-04

I'm new in js and js frameworks is there anywhere or any resource to give me full detailed information about fetch and JSON file? any time I think this JSON file is the same as the old one and when I start to show staff in page I get new errors, this specific is undefined (reading 'map') in Reactjs fetch JSON file structure:

{
    "success": true,
    "instantMenu": [
        {
            "title": "Admission",
            "url": ""
        },
        {
            "title": "Faculty members",
            "url": ""
        },
        {
            "title": "Research",
            "url": ""
        },
        {
            "title": "Campus",
            "url": ""
        }
    ],
    "mainMenu": [
        {
            "title": "About",
            "link": ""
        },
        {
            "title": "Presidency",
            "link": ""
        },
        {
            "title": "University Vice Chancellors",
            "link": ""
        },
        {
            "title": "Faculties",
            "link": ""
        },
        {
            "title": "Departments",
            "link": ""
        },
        {
            "title": "Research and Innovation",
            "link": ""
        },
        {
            "title": "Portals",
            "link": ""
        }
    ],

and Reactjs code is:

function Header() {
  const [body, fetchbody] = React.useState([]);
  const getData = () => {
        fetch('https://api.example.com/v1/body/en')
        .then((res) => res.json())
        .then((res) => {
          console.log(res);
          fetchbody(res?.body);
        });
  };
  React.useEffect(() => {
    getData()
  }, [])
  const [darkMode,setDarkMode]= React.useState(true);
  return (
    <header>
      <div id="myOverlay">
        <span className="closebtn" onClick={closeSearch()} title="Close Overlay">x</span>
      <div className="overlay-content">
        <form action="action_page.php">
          <input type="text" placeholder="search it" name="search"/>
          <button type="submit"><i className="fa fa-search"></i></button>
        </form>
      </div>
  </div>
    <div className='topbar'>
      <nav className="navbar navbar-expand-lg">
        <div className="container-fluid">
          <label className="topbar-lable" htmlFor=''>Action:</label>
          <ul className="navbar-nav me-auto mb-lg-0">
          {body['instantMenu'].map((instantMenu) =>  {
              return (
            <li className="nav-item">
              <a className="nav-link" aria-current="page" href={instantMenu.url}>{instantMenu.title}</a>
            </li>
               );
              })}
          </ul>

I try everything body.map body.length && body['instantMenu']?.title when I try this, console log gives me Cannot read properties of undefined (reading 'length') please help guys :) I want to learn and master it

CodePudding user response:

You could do this

function Header() {
  const [body, fetchbody] = React.useState({instantMenu:[], mainMenu:[]});
  const getData = () => {
        fetch('https://api.example.com/v1/body/en')
        .then((res) => res.json())
        .then((res) => {
          console.log(res);
          fetchbody(res?.body);
        });
  };
  React.useEffect(() => {
    getData()
  }, [])
  const [darkMode,setDarkMode]= React.useState(true);
  return (
    <header>
      <div id="myOverlay">
        <span className="closebtn" onClick={closeSearch()} title="Close Overlay">x</span>
      <div className="overlay-content">
        <form action="action_page.php">
          <input type="text" placeholder="search it" name="search"/>
          <button type="submit"><i className="fa fa-search"></i></button>
        </form>
      </div>
  </div>
    <div className='topbar'>
      <nav className="navbar navbar-expand-lg">
        <div className="container-fluid">
          <label className="topbar-lable" htmlFor=''>Action:</label>
          <ul className="navbar-nav me-auto mb-lg-0">
          {body['instantMenu'].map((instantMenu) =>  {
              return (
            <li className="nav-item">
              <a className="nav-link" aria-current="page" href={instantMenu.url}>{instantMenu.title}</a>
            </li>
               );
              })}
          </ul>

CodePudding user response:

Buddy! Use this to handle it in proper way:

function Header() {
  const [body, fetchbody] = React.useState([]);
  const getData = () => {
        fetch('https://api.example.com/v1/body/en')
        .then((res) => res.json())
        .then((res) => {
          console.log(res);
          fetchbody(res?.body);
        });
  };
  React.useEffect(() => {
    getData()
  }, [])
  const [darkMode,setDarkMode]= React.useState(true);
  return (
    <header>
      <div id="myOverlay">
        <span className="closebtn" onClick={closeSearch()} title="Close Overlay">x</span>
      <div className="overlay-content">
        <form action="action_page.php">
          <input type="text" placeholder="search it" name="search"/>
          <button type="submit"><i className="fa fa-search"></i></button>
        </form>
      </div>
  </div>
    <div className='topbar'>
      <nav className="navbar navbar-expand-lg">
        <div className="container-fluid">
          <label className="topbar-lable" htmlFor=''>Action:</label>
          <ul className="navbar-nav me-auto mb-lg-0">
          {body['instantMenu'] ? body['instantMenu'].map((instantMenu) =>  {
              return (
            <li className="nav-item">
              <a className="nav-link" aria-current="page" href={instantMenu.url}>{instantMenu.title}</a>
            </li>
               );
              }) : <li>-- Error in Data Fetch! --</li>}
          </ul>

the change i have mentioned in your code will at least not crash the view and give you hint what is the issue about!. Also this might not be the proper way to show error in menu but you must at least get hint how to do it for your own need.

I looked at your code more thoroughly!, I found you are initialising state with [] it should be {} instead!!!

CodePudding user response:

You should check if the attribute exists since the fetch might still be in execution when the page is loaded.
You can do it with conditional rendering:

<ul className='navbar-nav me-auto mb-lg-0'>
  {!body || !body.instantMenu
    ? 'Loading data...'
    : body['instantMenu'].map((instantMenu) => {
        return (
          <li className='nav-item'>
            <a className='nav-link' aria-current='page' href={instantMenu.url}>
              {instantMenu.title}
            </a>
          </li>
        );
      })}
</ul>;
  • Related