Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix "TypeError: categories.map is not a function" error in React

I keep getting this error that categories.map is not a function but I don't see why. I am setting categories to the data received from an API call but keep getting this error. Also, is there a way to call the children of a parent object easily? the API data is nested about 4-5 levels deep, and they all have different names, so how would I go about iterating through all of them?

Example of what response.data looks like in the console (with some the nested objects opened up)

enter image description here

Here's my component:

class Menu extends React.Component {
  state = {
    categories: []
  };

  componentDidMount() {
    axios
      .get("https://www.ifixit.com/api/2.0/categories")
      .then(response => this.setState({ categories: response.data }));
  } 

  render() {
    let categories = this.state.categories;
    return (
      <div>
        <ul>
          {categories.map((m, index) => {
            return (
              <li key={index}>
                {m.children && <Menu categories={m.children} />}
              </li>
            );
          })}
        </ul>
      </div>
    );
  }
}

export default Menu;

EDIT: When I use Object.keys it gives me the error "Uncaught Invariant Violation: Objects are not valid as a React child (found: object with keys...)" and then lists all keys within the objects I'm calling. Does anyone know how I can call the function (possibly recursively?) to apply this to all the objects within objects?

Here is my updated code:

class Menu extends React.Component {
  state = {
    collapsed: false,
    categories: []
  };

  componentDidMount() {
    axios
      .get("https://www.ifixit.com/api/2.0/categories")
      .then(response => this.setState({ categories: response.data}));
  } 

  render() {
    const { categories } = this.state;
    return (
      <div>
        {Object.keys(categories).map((item, i) => (
          <li key={i}>
            <span>{categories[item]}</span>
          </li>
        ))}
      </div>
    );
  }
}

export default Menu;
like image 504
Emily Avatar asked May 08 '26 13:05

Emily


2 Answers

You can map your properties object to array and handle it.

let result = Object.entries(data).map(( [k, v] ) => ({ [k]: v }));

Change to

componentDidMount() {
    axios
      .get("https://www.ifixit.com/api/2.0/categories")
      .then(response => this.setState({ 
       categories: Object.entries(response.data).map(( [k, v] ) => ({ [k]: v }) }));
  } 
like image 110
Hien Nguyen Avatar answered May 10 '26 01:05

Hien Nguyen


The problem is that response.data is not array but it is a json object.

You can map based on the keys using the following code:

Object.keys(categories).map((key, index) => {
  console.log(categories[key]);
});
like image 43
Zolfekar Askarieh Avatar answered May 10 '26 03:05

Zolfekar Askarieh



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!