Home > Mobile >  Material ui Select component is not working - "Error: choices.map is not a function"
Material ui Select component is not working - "Error: choices.map is not a function"

Time:06-05

I'm struggling to have a select component to drop down a list of states(of Brazil), where I could use in several forms inside the application(clients,suppliers, etc.). So, I made a Select component separately, and I want to use this "Select" component in my Bank form, to chose the state(location) where the bank is located. I'm getting an error in the map function, at the Selection component, and also, the form bank crashed, I don't know how to use the array's Select in the bank form properly. What to import and how to handle inside the bank form? I'll appreciate all helps received. I'm using Material-ui 5.0 and React 18.0 and Linux Ubunto 20.04.

// Bank form 
// Select is at 3/4 down bellow
import { Container } from '@mui/material';
import { Typography } from '@mui/material';
import { Box } from '@mui/material';
import { TextField } from '@mui/material';
import { makeStyles } from '@mui/styles';
import { Button } from '@mui/material';
import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight';
import Grid from '@mui/material/Grid';
import choices from '../components/Select';
import Controls from '../components/Controls';

const initialValues = {
    id: 0,
    fullName: '',
    address: '',
    local: '',
    city: '',
    CEP: '',
    phone: '',
    contact: '',
    email: '',
    numBank: '',
    branch: '',
    account: '',
    balance: '',
    date: '',
    stateId: '',

}


const useStyles = makeStyles((theme) => {
    return{
        root: {
            '& .MuiFormControl-root': {
                margim: theme.spacing(1) 
            },

            display: "flex",
            flexwrap: "wrap",
            
            
        },
        textField: {
            margimLeft: theme.spacing(1),
            margimRight: theme.spacing(1),
            width: "25ch",
        },
        
        field: {
            spacing: 2,
            display: "block",
        }
    }
});

export default function Bancos(){
    const classes = useStyles()
    const [name, setName] = useState('');
    const [address, setAddress] = useState('');
    const [nameError, setNameError] = useState(false);
    const [addressError, setAddressError] = useState(false);
    const [numBank, setNumBank] = useState('');
    const [branch, setBranch] = useState('');
    const [account, setAccount] = useState('');
    const [numBankError, setNumBankError] = useState(false);
    const [branchError, setBranchError] = useState(false);
    const [accountError, setAccountError] = useState(false);
    const [values, setValues] = useState(initialValues); 


const handleSubmit = (e) => {
    e.preventDefault()
    setNameError(false)
    setAddressError(false)

    if(name == ''){
        setNameError(true)
    }

    if( address == ''){
        setAddressError(true)
    }
    if ( numBank == ''){
        setNumBankError(true)
    }
    if (branch == ''){
        setBranchError(true)
    }
    if (account == ''){
        setAccountError(true)
    }
}

const handleInputChange = (e) => {
    const { name, value } = e.target
    setValues({
        ...values,
        [name]: value
    })

}

    return(
     
        <Container>
        <Typography  variant="h6" color="textSecondary" align="center" gutterBottom
         className="titleBank">
            Cadastro de Bancos
        </Typography>

        <form noValidate autoComplete="off" onSubmit={handleSubmit}>
            <Grid container spacing={2}>
                <Box mt={3} mb={1}> {/* colocar margim top e bottom com box   */}
                <Grid item xs={6} md={6}>
                <TextField label="Nome do Banco" variant="outlined" color="secondary"
                sx={{width: "430px", ml: 2}} required className={classes.field} name="fullName"
                value={values.fullName} error={ nameError }
                onChange={ handleInputChange }/>
               
                </Grid></Box>
            
                 <Box mt={1}>
                 <Grid item xs={6} md={10} style={{ display: "flex" }}>
                 <TextField label="Endereço" variant="outlined" color="secondary"
                 sx={{width: "650px", mr: 1, ml: 2}} required className={classes.field} name="address"
                 value={values.address}
                onChange={handleInputChange} error={addressError}/>
                <TextField label="Bairro"  className={classes.textField} name="local"
                 sx={{width: "350px" }}  value={ values.local }
                 onChange={ handleInputChange }  />
                </Grid></Box>
                <Grid item xs={6} md={10} style={{ display: "flex", margimLeft: 0}}>

                <TextField label="Cidade"  className={classes.field} name="city"
                sx={{width: "320px", mr: 1 }}  value={values.city}
                onChange={ handleInputChange } />

                 <TextField label="CEP"  className={classes.field} name="CEP"
                 sx={{width: "180px", mr: 1}} value={ values.CEP } 
                 onChange={ handleInputChange }/> 
               
                <TextField label="Contato" className={classes.field} name="contact"
                sx={{width: "350px", mr: 1 }} value={ values.contact} 
                onChange={ handleInputChange } />
                </Grid>

                <Grid item xs={6} md={10} style={{ display: "flex", margimLeft: 0}}>
                <TextField label="Telefone"  className={classes.field} name="phone"
                 sx={{width: "235px", mr: 1 }} value={ values.phone }
                 onChange={ handleInputChange } />
                 <TextField label="Celular"  className={classes.field} name="phone"
                 sx={{width: "235px", mr: 1 }} value={ values.phone }
                 onChange={ handleInputChange } />
                <TextField label="E-mail"  className={classes.field} name="email"
                 sx={{width: "350px", mr: 1 }} value={values.email} 
                 onChange={ handleInputChange } />
              
                 </Grid><br/>
                
                 <Grid item xs={6} md={10} style={{ display: "flex", margimLeft: 0}}>
                 <**Controls.Select**  sx={{width: "150px", mr: 2 }}
                    name="state"
                    label="Estado"
                    value={values.stateId}
                    onChange={handleInputChange}
                    options=**{choices}**
                 />    
                 <TextField label="Nº do Banco" className={classes.field} required
                 sx={{width: "100px", mr: 1 }} name="numBank" value={values.numBank}
                 onChange={ handleInputChange } error={ numBankError } />   
                 <TextField label="Nº Agência" className={classes.field} name="branch"
                 sx={{width: "150px", mr: 1 }} value={ values.branch } required
                 onChange={ handleInputChange } error={ branchError } />
                <TextField label="Nº Conta Corrente" className={classes.field} name="account"
                 sx={{width: "250px", mr: 1 }}  value={ values.account } required 
                 onChange={ handleInputChange } error={ accountError } />
                 <TextField label="Saldo R$"  className={classes.field} name="balance"
                 sx={{width: "180px", mr: 1 }} value={ values.balance } 
                 onChange={ handleInputChange } />
                 </Grid><br/>
                 <Grid item xs={6} md={8} style={{ display: "flex" }}> 
                <Box mt={4}> {/* colocar margim top e bottom com box   */}
                <Button type="submit" variant="contained" color="primary"
                 endIcon={<KeyboardArrowRightIcon />} 
                >
                 Salvar
                </Button>
                </Box>
                </Grid>
            </Grid>            
        </form>

        </Container>
    
    )
}
import React from 'react'
import {FormControl, InputLabel, Select as MuiSelect,  MenuItem }  from '@mui/material';

// Select component with all states

export default function Select(props) {

  const choices = () => ([
    { id: '1', title: 'Acre'}, 
    { id: '2', title: 'Alagoas'},
    { id: '3', title: 'Amazonas' },
    { id: '4', title: 'Amapá'   }, 
    { id: '5', title: 'Bahia'  }, 
    { id: '6', title: 'Distrito Federal'}, 
    { id: '7', title: 'Espírito Santo' }, 
    { id: '8', title: 'Mato Grosso do Sul'}, 
    { id: '9', title: 'Mato Grosso'}, 
    { id: '10', title: 'Rio de Janeiro'}, 
    { id: '11', title:  'São Paulo' }, 
    { id: '12', title: 'Minas Gerais'}, 
    { id: '13', title: 'Paraná'  }, 
    { id: '14', title: 'Santa Catarina'}, 
    { id: '15', title:  'Sergipe' }, 
    { id: '16', title: 'Paraíba' }, 
    { id: '17', title: 'Pernambuco'}, 
    { id: '18', title:  'Goiás'  }, 
    { id: '19', title: 'Roraima'}, 
    { id: '20', title: 'Rondônia'}, 
    { id: '21', title: 'Santa Catarina'}, 
    { id: '22', title: 'Rio Grande do Sul'}, 
    { id: '23', title: 'Rio Grande do Norte'},
    { id: '24', title: 'Maranhão'}
   
  
  ]);
  

const { name, label, value, onChange } = props; 

console.log(choices);

  return (
    <FormControl  variant="outlined">
      <InputLabel>{label}</InputLabel>
      <MuiSelect label={label} name={name} value={value} onChange={onChange}>
        <MenuItem value="">none</MenuItem>
          {
            choices.map(
              item => (<MenuItem key={item.id} value={item.id}>{item.title}</MenuItem>)
            )
          }

        </MuiSelect>

      </FormControl>
    

  )
}
// Uncaught TypeError: choices.map is not a function  at Select (Select.js:46:1)
// The above error occurred in the <Select> component

CodePudding user response:

In your component choices is a function that returns array of choices.

CodePudding user response:

TL;DR;

change the code from :

      {
        choices.map(
          item => (<MenuItem key={item.id} value={item.id}>{item.title}</MenuItem>)
        )
      }

to

         {
            choices()?.map(
              item => (<MenuItem key={item.id} value={item.id}>{item.title}</MenuItem>)
            )
          }

Why My code is not working ?

You have defined choices as a function not a variable. So You need to call it in order to get the value.

Alternatively you can correct the mistake by defining the vairable as below :

const choices = [
    { id: '1', title: 'Acre'},
       // .... other items
]

CodePudding user response:

use choices().map instead of choices.map.

  • Related