5

I am trying to populate a select component from Material UI with data from my database. I can successfully show the data in the component, but when I select one option it breaks and the following error "categorias.map is not a function" shows up. Does anybody know what am I doing wrong? Here is the code:

<FormControl className={classes.formControl}>
  <InputLabel id="demo-simple-select-label">Categorias</InputLabel>
    <Select
      labelId="demo-simple-select-filled-label"
      id="demo-simple-select-filled"
      value={categorias}
      onChange={(ev) => setCategorias(ev.target.value)}
    >
      <MenuItem value="">
        <em>None</em>
      </MenuItem>
      {categorias.map((categoria) =>
        <MenuItem value={categoria.id}>{categoria.nombre}</MenuItem>
      )}
    </Select>
</FormControl>

Here is more code regarding categorias:

const [categorias, setCategorias] = useState([]);


  useEffect(() => {

      const getCategorias = async () => {
        const res = await fetch("/categories", {
            method: 'GET',
            headers: {'Content-Type': 'application/json'},
        })
        //console.log(res);
        const response = await res.json();
        setCategorias(response);
        console.log(categorias);
      }
      getCategorias();
  })

Thank you!

4 Answers 4

2

One of the common causes could be categorias might be not have a default value i.e. undefined before the rest call completes.

if you give the variable a default value like '[]' it might solve your problem. Or,if you are using es2020, you could try categorias?.map(...)

I think it would be helpful if you can show the code leading up to the render to help us understand the problem better.

update: based on useEffects code, you might want to check your endpoint to ensure it's returning an array of objects for you

Sign up to request clarification or add additional context in comments.

2 Comments

Hi, it does return an array. The select component shows the objects but when I select one of them is when the error shows.
I don't think mateial ui drop can accept an object as value. if the endpoint is returnning the object in this format: [{id:1, nombre:1}], you probably need another state to store your selection from the drop down, and onChange to update this state instead of categorias
1

The issue is that you is that you are replacing your array of categorias with an object with the onChange event, which then means that categorias is no longer an array so it cant use .map which is why you are getting an error

What you need to do is create another state to hold the selected value

import React, { useState, useEffect } from "react";
import { makeStyles } from "@material-ui/core/styles";
import InputLabel from "@material-ui/core/InputLabel";
import MenuItem from "@material-ui/core/MenuItem";
import FormControl from "@material-ui/core/FormControl";
import Select from "@material-ui/core/Select";

const useStyles = makeStyles((theme) => ({
  formControl: {
    margin: theme.spacing(1),
    minWidth: 120
  }
}));

export default function SimpleSelect() {
  const classes = useStyles();
  const [categorias, setCategorias] = useState([]);
  const [selectedCategorias, setselectedCategorias] = useState("");

  useEffect(() => {
    const getCategorias = async () => {
      const res = await fetch("/categories", {
        method: "GET",
        headers: { "Content-Type": "application/json" }
      });
      //console.log(res);
      const response = await res.json();
      setCategorias(response);
    };
    getCategorias();
  }, []);

  return (
    <FormControl className={classes.formControl}>
      <InputLabel id="demo-simple-select-label">Categorias</InputLabel>
      <Select
        labelId="demo-simple-select-filled-label"
        id="demo-simple-select-filled"
        value={selectedCategorias}
        onChange={(ev) => setselectedCategorias(ev.target.value)}
      >
        <MenuItem value="">
          <em>None</em>
        </MenuItem>
        {categorias.map((categoria) => (
          <MenuItem key={categoria.id} value={categoria.id}>{categoria.nombre}</MenuItem>
        ))}
      </Select>
    </FormControl>
  );
}

Another couple of issues I found is you are missing the key prop in the MenuItem, and in your useEffect you don't have any dependencies so it will run in an infinite loop. So I have included it so it only runs on mount.

Comments

0

What type is categorias? .map is a built-in method of the arrays prototype. If categories is no an array, that could be your problem. I'm guessing you're in react, so try console logging categories out to see what it is at run.

Comments

0

You could try this:

<MenuItem value="">
    <em>None</em>
</MenuItem>
{categorias & categorias.map((categoria) =>
    <MenuItem value={categoria.id}>{categoria.nombre}</MenuItem>
)}

1 Comment

While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value.

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.