0

I struggle to create a dynamic navigation component. The navigation items should be consumed from an Rest API generated by the backend (in my case Django).

The API relevant address displays the list entries correctly (see below). However, I cannot find a proper way to call these items in my NextJS application. In my case, under components/Navigation.js

I try to consume the pages information from the function getAllPages (./api/wagtail.js)

export async function getAllPages() {
    return await getRequest(`${API_URL}/v1/page_relative_urls/`);
}

In the browser the address

${API_URL}/v1/page_relative_urls/

displays the entries as expected and provides the below list:

{ "meta":
{ "total_count": 8 },
"items": [
{
"title": "Home Page",
"relative_url": "/"
},
{ "title": "About us",
"relative_url": "/about-us/"
},
...
]}

I tried then to use getAllPages in the compoenents/navigation.js:

import getAllPages from '../../api/wagtail.js'

const Navtest = () => {
    return <div className={s.Root}>

   <nav>
        {getAllPages.items.map((link, index) => {
          return (
            <ul>
              <Link href={link.title}>
                <li key={index}>{link.title}</li>
              </Link>
            </ul>
          );
        })}
      </nav>

    </div>;
};

Navtest.propTypes = {};

Navtest.defaultProps = {};

export default Navtest;

This raises an error message TypeError: Cannot read properties of undefined (reading 'items')

What am I'm doing wrong?

donbonbon
  • 81
  • 1
  • 8

1 Answers1

0

Async function always returns a Promise. So use .then to get its value.

import { getAllPages } from "../../api/wagtail.js";

const Navtest = () => {

  const [pages, setPages] = useState([]);

  useEffect(() => {
     getAllPages().then(result => setPages(result.items));
  }, []);

  return (
    <div className={s.Root}>
      <nav>
        {pages.map((link, index) => {
          return (
            <ul>
              <Link href={link.title}>
                <li key={index}>{link.title}</li>
              </Link>
            </ul>
          );
        })}
      </nav>
    </div>
  );
};

Navtest.propTypes = {};

Navtest.defaultProps = {};

export default Navtest;

Refer this question for deeper understanding of how async-await works.

Shri Hari L
  • 4,551
  • 2
  • 6
  • 18
  • If this is in React 18. It's better to replace the useEffect by useSWR – Jonathan Dsouza Jun 08 '23 at 08:19
  • Thanks @Shri Hari L, I add 'import {useState, useEffect} from react; and run the above code as is. It raises the error: 'TypeError: _api_wagtail_js__WEBPACK_IMPORTED_MODULE_1__["default"] is not a function' – donbonbon Jun 08 '23 at 08:37
  • Try destructuring your imports: `import { getAllPages } from '../../api/wagtail.js'` – Shri Hari L Jun 08 '23 at 08:59
  • Thanks @Shri Hari L, this then raises the error:'WagtailApiResponseError: Not Found. Url: undefined/v1/page_relative_urls/. Params: {}' – donbonbon Jun 08 '23 at 12:14
  • Also @Shri Hari L, the reference slackoverflow answer is very helpful. Thanks! – donbonbon Jun 08 '23 at 12:41
  • You're welcome. You can accept / upvote the answer if it helped you. Looks like `API_URL` is `undefined`. So check and fix the place where this variable resides. – Shri Hari L Jun 08 '23 at 13:11