2

I'm learning react and I took template as an example, I would like change menu values. The menus are create with fixed values, and I need to access my API and get values from the database, but when I try do that, I get an error return:

const LoadNavigation = async () => {
    return await axios.get('https://localhost:44362/api/SystemMenus').then(response => response.data);
}

var nav = LoadNavigation();

export const navigations = nav;

Error:

TypeError: Invalid attempt to spread non-iterable instance. In order to be iterable, non-array objects must have a Symbol.iterator method.

If I pass the fixed export value (json) it works:

export const navigations = [
    {
        name: 'Home',
        path: '/dashboard',
        icon: 'home',
    },
    {
        label: 'Dashboards',
        type: 'label',
    },
    {
        name: 'Test 1',
        icon: 'trending_up',
        children: [
            {
                name: 'Test 02',
                iconText: 'CP',
                path: '/test/test02',
            },
            {
                name: 'Test 03',
                iconText: 'FC',
                path: '/test/test03',
            },
        ],
    },
    
]

Another point is that my API is called after my const has been exported.

Promise

How do I solve these two problems, I couldn't find anything similar or that I could understand.

I did a lot of testing and modifying the code, but I can't get it to work.

EDIT - Answer @Giovanni Esposito

In this case it occurs and calls API

import axios from 'axios';

navigationsAPI.js

export const LoadNavigation = async () => {
    let response = await axios.get('https://localhost:44362/api/SystemMenus');
    return response.data;
}

navigation.js

import React from 'react';
import { LoadNavigation } from 'app/navigationsAPI'

var nav = LoadNavigation();

export const navigations = nav;

Error:

TypeError: Invalid attempt to spread non-iterable instance. In order to be iterable, non-array objects must have a Symbol.iterator method.

Error3

EDIT - Answer @Drew Reese

In this case only the error occurs, it does not call API

navigationsAPI.js

import axios from 'axios';

export const LoadNavigation = () => {
    return axios.get('https://localhost:44362/api/SystemMenus')
        .then(response => response.data);
}

navigation.js

import React from 'react';
import { LoadNavigation } from 'app/navigationsAPI'

const [nav, setNav] = React.useState([]);

React.useEffect(() => {
    LoadNavigation().then(setNav);
}, []);


export const navigations = nav;

Error:

Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:

  1. You might have mismatching versions of React and the renderer (such as React DOM)
  2. You might be breaking the Rules of Hooks
  3. You might have more than one copy of React in the same app

Erro2

2
  • LoadNavigation is an async function so it will return promise try using var nav=LoadNavigation.then(response => (return response)) Commented Aug 5, 2021 at 17:45
  • I tried removing async and await and the result was the same. I tried to follow your tip but there is a syntax error, the error is (return response). Is this after the LoadNavigation method? Commented Aug 5, 2021 at 18:06

2 Answers 2

1

You could adopt also this way:

navigationsAPI.js

import axios from 'axios';   

export const LoadNavigation = async () => {  
  let response = await axios.get('https://localhost:44362/api/SystemMenus');
  return response.data;
}

In any component in which you need to load navigation:

import React, { useState, useEffect } from 'react';
import { LoadNavigation } from './navigationsAPI'

const Component = () => {
   const [navigation, setNavigation] = useState();

   useEffect(() => {
      LoadNavigation().then(response => setNavigation(response));
      
   }, []);

   return (...);
}
Sign up to request clarification or add additional context in comments.

6 Comments

Giovanni Esposito, I tried to follow your example but i had the same initial problem. I edited the post to demonstrate. If you have any other solution, thank you
@user8223022 I saw your editing and I think that maybe I was not clear. Let me edit my answer.
I'm sorry for my ignorance, I'm trying to understand all this, but when I follow your example, the same problem as the Drew Reese example occurs, as it is in the original post. Error: Invalid hook call. Hooks can only be called inside the body of a function component. This could happen for one of the following reasons: 1. You might have mismatching versions of React and the renderer (such as React DOM) 2. You might be breaking the Rules of Hooks 3. You might have more than one copy of React in the same app
@user8223022 most probably because you are calling useEffect outside a component. This s mandatory for React otherwise you got this error. If you don't know what is a component you could read this
actually the error occurs const [navigation, setNavigation] = useState();. But is the cause also because it is outside a component?
|
1

Unless your system and browser supports top-level await (or similar behavior) this isn't possible to make the code wait for the response & handling before the navigations is exported. This probably isn't what you want to do anyway.

To handle this normally you could export the LoadNavigation function, and use a local navigations state variable and mounting effect to fetch and load the menu data.

export const LoadNavigation = () => {
  return axios.get('https://localhost:44362/api/SystemMenus')
    .then(response => response.data);
}

In consuming component;

const MyComponent = () => {

  const [navigations, setNavigations] = React.useState([]);

  React.useEffect(() => {
    LoadNavigation().then(setNavigations); // *
  }, []);

  ...

}

* Note: Here LoadNavigation().then(setNavigations); is passing the setNavigations function as the .then callback, but if it's more clear you can use an anonymous callback and proxy the response data.

React.useEffect(() => {
  LoadNavigation().then(data => setNavigations(data));
}, []);

2 Comments

Drew Reese, I followed your example, for me a little more complex, and I had another error other than the initial one, but this time the API is not called, anything else I can do? I edited the post to demonstrate the result. Thanks
@user8223022 You can't call React hooks outside a function component (or custom hook). Sorry, I assumed you understood how React hooks work. See Introducing Hooks. I'll update my answer to make this overtly clear.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.