4

Hoping I can get some help. I'm currently following a tutorial that is using React Material-UI, specifically to do with a simple Select drop-down.

They are using the following json dataset object snippet for their code that looks like this:

{
  "AF": "Afghanistan",
  "AL": "Albania",
  "DZ": "Algeria",
  "AS": "American Samoa",
  "AD": "Andorra",
  "AO": "Angola",
  "AI": "Anguilla"
}

and the React code they use to build the select is as follows, where options here is the above json dataset:

  return (
    <TextField>
      {Object.keys(options).map((item, pos) => {
        return (
          <MenuItem key={pos} value={item}>
            {options[item]}
          </MenuItem>
        )
      })}
    </TextField>
  );

Now I am trying to build something similar to the above but my dataset is actually an array of objects, i.e.:

[
    {
        "job_id": 1,
        "job_name": "Engineer"
    },
    {
        "job_id": 2,
        "job_name": "Scientist"
    },
    {
        "job_id": 3,
        "job_name": "Teacher"
    }
]

My question is, how can I achieve the above React code to construct my React Material UI Select but instead of using an object, I would like to use my array of objects where the name shown in the select drop-down is job_name and the value return is job_id?

I have tried the following, but nothing is returned:

{options.map(option => {
          return (
            <MenuItem key={option.value} value={option.value}>
              {option.key}
            </MenuItem>
          )
})}

Added: In addition to the above, what is the best way of checking between the first dataset (object) and my data set - array of objects and then using this check to distinguish between the two methods of displaying the data within the correct Material-UI Select code?

2 Answers 2

13

You need to access the item options differently since key and value are not set in the objects within the array. The possible options are job_id and job_name.

So try this:

{options.map(option => {
          return (
            <MenuItem key={option.job_id} value={option.job_id}>
              {option.job_name}
            </MenuItem>
          )
})}

Map will be called on every item so that option here is one of the elements in your array.

Update: to distinguish if the object is an array or not you could use Array.isArray:

{(Array.isArray(options) ? options.map(({job_id, job_name})=> ([job_id, job_name])) : Object.entries(options)).map(([key,value])=> {
          return (
            <MenuItem key={key} value={key}>
              {value}
            </MenuItem>
          )
})}

This would work but maybe should be done separately to keep the jsx lean and avoid overloading the render function.

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

1 Comment

I was almost there, just didn't use the correct attributes. I added an additional question about distinguishing b/w object and an array of objects as I would like to check for both types within my code.
2

A Complete example with sample component and sample URLs

import { FormControl, InputLabel, MenuItem, Select, SelectChangeEvent } from '@mui/material';
import axios from 'axios';
import * as React from 'react';
import { useEffect, useState } from 'react';

type Props = {};

export const ProductsSearch = (props: Props) => {
    var token = localStorage.getItem('token');
    const requestHeader = {
        headers: {
            Authorization: `Bearer ${token}`
        }
    };

    const [brands, setBrands] = useState<any[]>([]);
    const [categories, setCategories] = useState<any[]>([]);
    const [searchedProducts, setSearchedProducts] = useState<any[]>([]);

    const [brand, setBrand] = useState('');
    const handleChangeBrand = (event: SelectChangeEvent) => {
        setBrand(event.target.value);
    };

    const [category, setCategory] = useState('');
    const handleChangeCategory = (event: SelectChangeEvent) => {
        setCategory(event.target.value);
    };

    useEffect(() => {
        let brandsUrl = `http://localhost:5000/api/products/brands/all`;
        let categoriesUrl = `http://localhost:5000/api/products/categories/all`;
        let searchedProductsUrl = `http://localhost:5000/api/products/byBrandAndcategory/1/5`;

        axios.all([axios.get(brandsUrl, requestHeader), axios.get(categoriesUrl, requestHeader), axios.get(searchedProductsUrl, requestHeader)]).then(axios.spread((...responses) => {
            setBrands(responses[0].data);
            setCategories(responses[1].data);
            setSearchedProducts(responses[2].data);
        })).catch(errors => {
            console.log('Error fetching multiple requests');
        });
    }, []);

    return (
        <>
            <FormControl variant="filled" sx={{ m: 1, minWidth: 200 }}>
                <InputLabel id="brand-select-label">Brand</InputLabel>
                <Select
                    labelId="brand-select-label"
                    id="brand-select"
                    value={brand}
                    onChange={handleChangeBrand}
                >
                    {
                        brands.map((brand) => {
                            return <MenuItem value={brand.brand_id} key={brand.brand_id}>{brand.brand_name}</MenuItem>
                        })
                    }
                </Select>
            </FormControl>

            <FormControl variant="filled" sx={{ m: 1, minWidth: 200 }}>
                <InputLabel id="category-select-label">Category</InputLabel>
                <Select
                    labelId="category-select-label"
                    id="category-select"
                    value={category}
                    onChange={handleChangeCategory}
                >
                    {
                        categories.map((category) => {
                            return <MenuItem key={category.category_id} value={category.category_id}>{category.category_name}</MenuItem>
                        })
                    }
                </Select>
            </FormControl>

            {brands.length} | {categories.length} | {searchedProducts.length}
        </>
    );
};

Comments

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.