Material-UI FormControl InputLabel display problem - reactjs

In the picture, you can see that my label is behind the outline but I don't know why it is. I didn't give any kind of style I just gave a minWidth that's it but still, it's one kind of broken I mean the label is behind the line. Here is the code:
import React, { Component } from "react";
import {
Container, Grid, FormControl,
InputLabel, Select, MenuItem
} from "#material-ui/core";
import { withStyles } from "#material-ui/core/styles";
const styles = (theme) => ({
formControl: {
minWidth: 180
}
});
class Account extends Component {
constructor() {
super();
this.state = {
age: ""
};
this.handleChange = this.handleChange.bind(this);
}
handleChange = (event) => this.setState({ age: event.target.value });
render() {
const { classes } = this.props;
const { age } = this.state;
return (
<React.Fragment>
<Container>
<Grid container spacing={2}>
<Grid item xs={12} sm={12} md={12} lg={12} xl={12}>
<FormControl
className={classes.formControl}
variant="outlined"
size="small">
<InputLabel>Age</InputLabel>
<Select value={age} onChange={this.handleChange}>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
</Grid>
</Grid>
</Container>
</React.Fragment>
);
}
}
export default withStyles(styles, { withTheme: true })(Account);

The "Select" did not have enough space. To proof the theory I have added a < br > break to create some extra space. Now it displays the age above the Select Field. Please adjust the Margin Top.

import React, { Component, createRef } from "react";
import { Container, Grid, FormControl,
InputLabel, Select, MenuItem } from "#material-ui/core";
import { withStyles } from "#material-ui/core/styles";
const styles = (theme) => ({
formControl: {
minWidth: 180
}
});
class Account extends Component {
constructor() {
super();
this.state = {
age: '',
labelWidth: 0
};
this.handleChange = this.handleChange.bind(this);
this.inputLabel = createRef();
}
handleChange = (event) => this.setState({ age: event.target.value });
componentDidMount() {
this.setState({ labelWidth: this.inputLabel.current.offsetWidth });
}
render() {
const { classes } = this.props;
const { age, labelWidth } = this.state;
return (
<React.Fragment>
<Container>
<Grid container spacing={2}>
<Grid item xs={12} sm={12} md={12} lg={12} xl={12}>
<FormControl
className={classes.formControl}
variant="outlined"
size="small"
>
<InputLabel ref={this.inputLabel}>Age</InputLabel>
<Select
value={age}
onChange={this.handleChange}
labelWidth={labelWidth}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
</Grid>
</Grid>
</Container>
</React.Fragment>
);
}
}
export default withStyles(styles, { withTheme: true })(Account);

Related

How should I manage multiple select fields dynamically added in React JS?

This code adds dynamic input fields using react.
Two select dropdowns and one input text.
When clicking on add button. the same replica of these 3 input fields is added below the old input block.
When I change the value of one selected then it automatically changes other select input values. For example, you select the type of jewelry as a ring then, another type of jwellery also got reflected. I am beginner in react.
import React,{useState } from 'react'
import Grid from '#material-ui/core/Grid';
import TextField from '#material-ui/core/TextField';
import MenuItem from '#material-ui/core/MenuItem';
import FormControl from '#material-ui/core/FormControl';
import InputLabel from '#material-ui/core/InputLabel';
import Select from '#material-ui/core/Select';
import { makeStyles } from "#material-ui/core/styles";
import Button from '#material-ui/core/Button';
const backgroundShape = require('./images/background.svg');
const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1,
backgroundColor: '#064771',
overflow: 'hidden',
background: `url(${backgroundShape}) repeat`,
backgroundSize: 'cover',
backgroundPosition: '0 1000px',
paddingBottom: 500
},
action_btn:{
marginTop:'10px',
marginRight: "5px"
},
main_grid:{
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
margin:'auto',
display: 'flex',
}
}));
function App() {
const classes = useStyles();
//handle mmultiple input
const [state, setState] = React.useState({
gold_caratage: "",
gold_type: ""
});
// handle input change
const handleInputChange = (evt) => {
const value = evt.target.value;
setState({
...state,
[evt.target.name]: value
});
};
//clone form logic
const [inputList, setInputList] = useState([{ jwellary_type: "", net_gram: "",caratage:"" }]);
//remove and add btn logic
const handleRemoveClick = index => {
const list = [...inputList];
list.splice(index, 1);
setInputList(list);
};
// handle click event of the Add button
const handleAddClick = () => {
setInputList([...inputList, { jwellary_type: "", net_gram: "",caratage:"" }]);
};
return (
<div className={classes.root}>
<typography guttorbuttom align="center">
<h1>React Calc</h1>
</typography>
{inputList.map((x, i) => {
return (
<Grid container className={classes.main_grid} spacing={3}>
<Grid item xs={10} sm={2}>
<FormControl style={{ minWidth:140 }}>
<InputLabel id="demo-simple-select-label">Type Of Jwellary</InputLabel>
<Select
name="gold_type"
value={state.gold_type}
onChange={handleInputChange}
>
<MenuItem value={1}>Ring</MenuItem>
<MenuItem value={2}>Chain</MenuItem>
<MenuItem value={3}>Other</MenuItem>
</Select>
</FormControl>
</Grid>
<Grid item xs={10} sm={2}>
<TextField
name="Net Gram"
label="Net Gram"
type="number"
fullwidth
/>
</Grid>
<Grid item xs={10} sm={2}>
<FormControl style={{ minWidth: 120 }}>
<InputLabel id="demo-simple-select-label">Caratage</InputLabel>
<Select
value={state.gold_caratage}
onChange={handleInputChange}
name="gold_caratage"
>
<MenuItem value={1}>22</MenuItem>
<MenuItem value={2}>23</MenuItem>
<MenuItem value={3}>24</MenuItem>
</Select>
</FormControl>
</Grid>
<Grid item xs={10} sm={2}>
<Button
variant="contained"
color="secondary"
className={classes.action_btn}
onClick={() => handleRemoveClick(i)}>
Remove
</Button>
<Button
variant="contained"
color="primary"
className={classes.action_btn}
onClick={handleAddClick}>
Add
</Button>
</Grid>
</Grid>
);
})}
</div>
)
}
export default App;
Issue
The main issue here is that you've a single state that is used for all the input values and other than index there is no way to differentiate one set of inputs from the next.
Solution
When adding new input sets to the inputList you will want to assign unique id properties to each set. This serves a couple purposes:
The id can be used as the React key for each mapped input set. This helps with rerendering and reconciliation when input sets are deleted.
You can use the id for updating and deleting state.
There is no need for the separate input state state, the inputList state has all the data necessary.
import { v4 as uuidV4 } from 'uuid';
export default function App() {
const classes = useStyles();
//clone form logic
const [inputList, setInputList] = useState([
{
id: uuidV4(), // <-- provide id
jwellary_type: "",
net_gram: "",
caratage: ""
}
]);
// handle input change
const handleInputChange = (id) => (evt) => {
const { value } = evt.target;
setInputList((list) =>
list.map((el) => // <-- shallow copy array
el.id === id // <-- match by id
? {
...el, // <-- shallow copy element
[evt.target.name]: value // <-- update key/value
}
: el // <-- or return current element
)
);
};
//remove and add btn logic
const handleRemoveClick = (id) => {
// <-- shallow copy array and remove elements with mismatch id
setInputList((list) => list.filter((el) => el.id !== id));
};
// handle click event of the Add button
const handleAddClick = () => {
setInputList([
...inputList,
{
id: uuidV4(), // <-- provide id
jwellary_type: "",
net_gram: "",
caratage: ""
}
]);
};
return (
<div className={classes.root}>
<typography guttorbuttom align="center">
<h1>React Calc</h1>
</typography>
{inputList.map((x, i) => {
return (
<Grid
key={x.id} // <-- provide id as React key
container
className={classes.main_grid}
spacing={3}
>
<Grid item xs={10} sm={2}>
<FormControl style={{ minWidth: 140 }}>
<InputLabel id="demo-simple-select-label">
Type Of Jwellary
</InputLabel>
<Select
name="jwellary_type" // <-- name to match property
value={x.jwellary_type} // <-- current property
onChange={handleInputChange(x.id)} // <-- pass id
>
<MenuItem value={1}>Ring</MenuItem>
<MenuItem value={2}>Chain</MenuItem>
<MenuItem value={3}>Other</MenuItem>
</Select>
</FormControl>
</Grid>
<Grid item xs={10} sm={2}>
<TextField
name="Net Gram"
label="Net Gram"
type="number"
fullwidth
/>
</Grid>
<Grid item xs={10} sm={2}>
<FormControl style={{ minWidth: 120 }}>
<InputLabel id="demo-simple-select-label">Caratage</InputLabel>
<Select
value={x.caratage} // <-- current property
onChange={handleInputChange(x.id)} // <-- pass id
name="caratage" // <-- name to match property
>
<MenuItem value={1}>22</MenuItem>
<MenuItem value={2}>23</MenuItem>
<MenuItem value={3}>24</MenuItem>
</Select>
</FormControl>
</Grid>
<Grid item xs={10} sm={2}>
<Button
variant="contained"
color="secondary"
className={classes.action_btn}
onClick={() => handleRemoveClick(x.id)} // <-- pass id
>
Remove
</Button>
<Button
variant="contained"
color="primary"
className={classes.action_btn}
onClick={handleAddClick}
>
Add
</Button>
</Grid>
</Grid>
);
})}
</div>
);
}

Required TextField validation on Material-UI

If something is written on the required TextField then everything will be okay but if the required TextField is blank then it will show me an error message on a helperText. But the problem is I can't use lenth on a if condition where I have set an onClick handler or method but I can use lenth on an onChange handler or method. If I can't use lenth then how will I know that something is written on required TextField. Here is my code:
import React, { Component } from 'react';
import { Container, Grid, Typography, TextField, Button } from '#material-ui/core';
import { withStyles } from "#material-ui/core/styles";
const styles = theme => ({
mT: {
marginTop: theme.spacing(1)
},
mR: {
marginRight: theme.spacing(3)
}
});
class Account extends Component {
constructor(){
super()
this.state={
accname: '',
helperText: '',
error: false
}
this.onChange = this.onChange.bind(this);
this.onClick = this.onClick.bind(this);
}
onChange = (event) => {
this.setState({[event.target.name]:event.target.value})
}
onClick = (event) => {
if (event.target.required > 0) {
this.setState({ helperText: '', error: false });
} else {
this.setState({ helperText: 'Invalid format', error: true });
}
}
render() {
const { classes } = this.props;
return (
<React.Fragment>
<Container>
<Grid container
spacing={2}>
<Grid item
xs={12}
sm={12}
md={12}
lg={12}
xl={12}>
<Typography className={classes.mT}
variant="h4"
color="textPrimary">
Add Account
</Typography>
</Grid>
<Grid item
xs={12}
sm={12}
md={12}
lg={12}
xl={12}>
<TextField className={classes.mR}
label="Account Name"
name="accname"
type="text"
helperText={this.state.helperText}
onChange={this.onChange}
value={this.state.accname}
error={this.state.error}
variant="outlined"
color="primary"
size="small"
autoFocus
required />
<Button variant="contained"
color="primary"
onClick={this.onClick} >
Submit
</Button>
</Grid>
</Grid>
</Container>
</React.Fragment>
);
}
}
export default withStyles(styles, { withTheme: true })(Account);
onClick = () => {
if(
this.state.accname.trim() != '' &&
this.state.firstName.trim() != '' &&
this.state.lastName.trim() != ''
){
//Your API call here
}
else{
alert("fill the empty spaces!");
}

Using a checkbox with Material UI to change the boolean value of an attribute within redux

I have a form that is controlled by redux state and I need to use checkboxes that will change the value of certain attributes of state from true to false and back again. The way that I have it written, I can click the checkbox and it updates the attribute to true but when I try to click on it again, it doesn't uncheck and it doesn't change state.
Here is my form,
import React, { useEffect } from 'react';
import Avatar from '#material-ui/core/Avatar';
import Button from '#material-ui/core/Button';
import CssBaseline from '#material-ui/core/CssBaseline';
import TextField from '#material-ui/core/TextField';
import {Link} from 'react-router-dom'
import Grid from '#material-ui/core/Grid';
import Box from '#material-ui/core/Box';
import EditIcon from '#material-ui/icons/Edit';
import Typography from '#material-ui/core/Typography';
import { makeStyles } from '#material-ui/core/styles';
import Container from '#material-ui/core/Container';
import {connect} from 'react-redux'
import {updateProfileForm, setProfileForm} from '../actions/updateProfileActions'
import { update } from '../actions/currentUserActions'
import FormControl from '#material-ui/core/FormControl';
import Checkbox from '#material-ui/core/Checkbox';
import FormControlLabel from '#material-ui/core/FormControlLabel';
import FormGroup from '#material-ui/core/FormGroup';
import FormLabel from '#material-ui/core/FormLabel';
import { TimePicker } from "#material-ui/pickers"
function Copyright() {
return (
<Typography variant="body2" color="textSecondary" align="center">
{'Copyright © '}
<Link color="inherit" href="https://material-ui.com/">
NTXASN
</Link>{' '}
{new Date().getFullYear()}
{'.'}
</Typography>
);
}
const useStyles = makeStyles((theme) => ({
paper: {
marginTop: theme.spacing(8),
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
},
avatar: {
margin: theme.spacing(1),
backgroundColor: theme.palette.secondary.main,
},
form: {
width: '100%', // Fix IE 11 issue.
marginTop: theme.spacing(3),
},
submit: {
margin: theme.spacing(3, 0, 2),
},
}));
const UpdateProfileForm =({updateFormData, updateProfileForm, update, history, currentUser, setProfileForm })=> {
const useUpdateProfileForm = () => {
useEffect(()=> {
setProfileForm(currentUser.attributes)
}, [])
}
useUpdateProfileForm()
const classes = useStyles();
const handleChange = event => {
const {name, value } = event.target
const updatedFormInfo = {
...updateFormData,
[name]: value
}
updateProfileForm(updatedFormInfo)
}
const handleBoolean = event => {
const {name, value } = event.target
console.log(event.target.checked)
const updatedFormInfo = {
...updateFormData,
[name]: !value
}
updateProfileForm(updatedFormInfo)
console.log(event.target.checked)
}
const handleSubmit = event =>{
event.preventDefault()
update(updateFormData, history)
}
return (
<Container component="main" maxWidth="xs">
<CssBaseline />
<div className={classes.paper}>
<Avatar className={classes.avatar}>
<EditIcon />
</Avatar>
<Typography component="h1" variant="h5">
Update your Driver Profile
</Typography>
<form className={classes.form} noValidate onSubmit={handleSubmit}>
<Grid container spacing={2}>
<Grid item xs={12}>
<TextField
name="name"
variant="outlined"
required
fullWidth
id="name"
label="Name"
autoFocus
onChange={handleChange}
value={updateFormData.name}
/>
</Grid>
<Grid item xs={12}>
<TextField
variant="outlined"
required
fullWidth
id="email"
label="Email Address"
name="email"
autoComplete="email"
onChange={handleChange}
value={updateFormData.email}
/>
</Grid>
<Grid item xs={12}>
<TextField
variant="outlined"
required
fullWidth
id="phone_number"
label="Phone Number"
name="phone_number"
autoComplete="phone number"
onChange={handleChange}
type="tel"
value={updateFormData.phone_number}
/>
</Grid>
<FormControl component="fieldset" className={classes.formControl}>
<FormLabel component="legend">Select Available Days</FormLabel>
<FormGroup>
<FormControlLabel
control={<Checkbox checked={updateFormData.monday} onChange={handleBoolean} name="monday" />}
label="Monday"
/>
<FormControlLabel
control={<Checkbox checked={updateFormData.tuesday} onChange={handleBoolean} name="tuesday" />}
label="Tuesday"
/>
<FormControlLabel
control={<Checkbox checked={updateFormData.wednesday} onChange={handleBoolean} name="wednesday" />}
label="Wednesday"
/>
</FormGroup>
</FormControl>
<FormControl component="fieldset" className={classes.formControl}>
<FormLabel component="legend">-</FormLabel>
<FormGroup>
<FormControlLabel
control={<Checkbox checked={updateFormData.thursday} onChange={handleBoolean} name="thursday" />}
label="Thursday"
/>
<FormControlLabel
control={<Checkbox checked={updateFormData.friday} onChange={handleBoolean} name="friday" />}
label="Friday"
/>
<FormControlLabel
control={<Checkbox checked={updateFormData.saturday} onChange={handleBoolean} name="saturday" />}
label="Saturday"
/>
</FormGroup>
</FormControl>
<FormControl component="fieldset" className={classes.formControl}>
<FormLabel component="legend">-</FormLabel>
<FormGroup>
<FormControlLabel
control={<Checkbox checked={updateFormData.sunday} onChange={handleBoolean} name="sunday" />}
label="Sunday"
/>
</FormGroup>
</FormControl>
</Grid>
<br/>
<Grid>
<TimePicker autoOk label="Hour Availability Lower Limit" value={updateFormData.availability_hours_lower} name="availability_hours_lower" onChange={handleChange}/>
<TimePicker autoOk label="Hour Availability Upper Limit" value={updateFormData.availability_hours_lower} name="availability_hours_upper" onChange={handleChange}/>
</Grid>
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
className={classes.submit}
>
Update Profile
</Button>
</form>
</div>
<Box mt={5}>
<Copyright />
</Box>
</Container>
);
}
const mapStateToProps = state => {
return{
currentUser: state.currentUser,
updateFormData: state.updateProfile
}
}
export default connect(mapStateToProps, {updateProfileForm, update, setProfileForm})(UpdateProfileForm)
here are my actions
export const updateProfileForm = (formData) => {
return {
type: "UPDATE_PROFILE_FORM",
formData: formData
}
}
export const resetProfileForm = () => {
return {
type: "RESET_PROFILE_FORM",
}
}
export const setProfileForm = (formData) => {
return {
type: 'SET_PROFILE_FORM',
formData: formData
}
}
here is my reducer
const initialState = {
name: '',
email: '',
phone_number: '',
monday: false,
tuesday: false,
wednesday: false,
thursday: false,
friday: false,
saturday: false,
sunday: false,
availability_hours_lower: '',
availability_hours_upper: ''
}
const updateProfileReducer = (state = initialState, action) => {
switch(action.type){
case "UPDATE_PROFILE_FORM":
console.log(action.formData)
return action.formData
case "RESET_SIGNUP_FORM":
return initialState
case "SET_PROFILE_FORM":
return action.formData
default:
return state
}
}
export default updateProfileReducer
As I stated, right now when I click the check box it updates redux state from false to true and renders a checked box but when I try to uncheck the box, redux state is not updated and it does not uncheck the box. Any help would be greatly appreciated!
You should use the checked attribute to check if the checkbox is on or not.
const handleBoolean = (event) => {
const { name, checked } = event.target
updateProfileForm({
...updateFormData,
[name]: checked,
})
}
This is unrelated to the question but you can refactor your handleChange and handleBoolean functions by updating the reducer to apply the changes to the existing state.
const updateProfileReducer = (state = initialState, action) => {
switch (action.type) {
case 'UPDATE_PROFILE_FORM':
return { ...state, ...action.formData }
// ...
default:
return state
}
}
const handleChange = (event) => {
const { name, value } = event.target
updateProfileForm({
[name]: value,
})
}
const handleBoolean = (event) => {
const { name, checked } = event.target
updateProfileForm({
[name]: checked,
})
}
Btw, you don't even need to manage the form state in Redux since it's a local state. I would recommend using React Hook Form to simplify the code.

Material ui list of select item need to be selected

i have created selected box..using functional component...i am getting list of items from the back end, i am looping that list and showing in the front end....now i need to be selected item need to show in the box what i have selected...could any one help on this...
Please see my example code in this link https://codesandbox.io/s/gallant-water-fnqiv
import React 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
},
selectEmpty: {
marginTop: theme.spacing(2)
}
}));
const lists = ["Ten", "twenty", "Thirty", "Fourty", "Fifity", "Sixty"];
export default function SimpleSelect() {
const classes = useStyles();
const [age, setAge] = React.useState("");
const inputLabel = React.useRef(null);
const [labelWidth, setLabelWidth] = React.useState(0);
React.useEffect(() => {
setLabelWidth(inputLabel.current.offsetWidth);
}, []);
const handleChange = event => {
setAge(event.target.value);
};
return (
<div>
<FormControl variant="outlined" className={classes.formControl}>
<InputLabel ref={inputLabel} id="demo-simple-select-outlined-label">
Age
</InputLabel>
<Select
labelId="demo-simple-select-outlined-label"
id="demo-simple-select-outlined"
value={age}
onChange={handleChange}
labelWidth={labelWidth}
>
<MenuItem value={""}>
{lists.map(item => {
<li>{item.list}</li>;
})}
</MenuItem>
</Select>
</FormControl>
</div>
);
}
There is no property in the array named, item.list , so you need to use item alone which itself gives the value you want.
Also make sure <MenuItem value={item}> is inside the lists.map() method..
Include return statement of the MenuItemis inside ofthe lists.map() method which throws error in your codesandbox link
And hence,
Change:
<MenuItem value={""}>
{lists.map(item => {
<li>{item.list}</li>;
})}
</MenuItem>
To:
{lists.map(item => {
return (
<MenuItem value={item}>
<li>{item}</li>
</MenuItem>
);
})}
Forked Codesandbox
you can try this-
<div>
<FormControl variant="outlined" className={classes.formControl}>
<InputLabel ref={inputLabel} id="demo-simple-select-outlined-label">
Age
</InputLabel>
<Select
labelId="demo-simple-select-outlined-label"
id="demo-simple-select-outlined"
value={age}
onChange={handleChange}
labelWidth={labelWidth}
>
{lists.map(item => (
<MenuItem value={item}>{item}</MenuItem>
))}
</Select>
</FormControl>
</div>
https://codesandbox.io/s/material-ui-select-m8lgt
Updated code sandbox link
Your MenuItem was wrong.
{lists.map(item => (
<MenuItem value={item}>{item}</MenuItem>
))}

Select MenuItem doesn't show when JSX saved to state

Working from the demo here: https://material-ui.com/demos/selects/ and I'm receiving some weird results. Specifically, when I select an item from the drop-down menu, the this.props.value updates fine... but the MenuItem does not show up.
If I put the <FormControl> tag directly in render, it works fine. If I put in an a variable, then setState with that and insert that into the render... it does NOT work.
Example:
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } 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 styles = theme => ({
root: {
display: 'flex',
flexWrap: 'wrap',
},
formControl: {
margin: theme.spacing.unit,
minWidth: 120,
},
selectEmpty: {
marginTop: theme.spacing.unit * 2,
},
});
class Question extends React.Component {
state = {
age: '',
age2: '',
slct: ''
};
componentDidMount() {
const { classes } = this.props;
var mySelect =
<FormControl className={classes.formControl}>
<InputLabel htmlFor="age-simple">Age</InputLabel>
<Select
value={this.state.age}
onChange={this.handleChange}
inputProps={{
name: 'age',
id: 'age-simple',
}}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
this.setState({ slct: mySelect });
}
handleChange = event => {
this.setState({ [event.target.name]: event.target.value });
};
render() {
const { classes } = this.props;
return (
<div>
{this.state.slct}
<p>Value:</p>{this.state.age}
<FormControl className={classes.formControl}>
<InputLabel htmlFor="age-simple2">Age</InputLabel>
<Select
value={this.state.age2}
onChange={this.handleChange}
inputProps={{
name: 'age2',
id: 'age-simple2',
}}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
<p>Value:</p>{this.state.age2}
</div>
);
}
}
export default withStyles(styles)(Question);
You can see how the 'value' updates correctly for both based on which answer I select in the drop down... but visually, the MenuItem label never appears to show up for the one that's coming from state:
Help?
(fyi: these items are in a parents' <form>.)
it has to be a function or an Array for rendering. To make your code work, it should be:
state = {
slct: <FormControl>...</FormControl>
}
slctRenderer = () => this.state.slct;
render() {
return (
<div>
{this.slctRenderer()}
</div>
);
}
Using the information from #Jee Mok ... the idea that it might work as a function (even though other items don't seem to care) made me try the following changes to the initial code:
Added this function:
selectRenderer() {
const { classes } = this.props;
return (
<FormControl className={classes.formControl}>
<InputLabel htmlFor="age-simple">Age</InputLabel>
<Select
value={this.state.age}
onChange={this.handleChange}
inputProps={{
name: 'age',
id: 'age-simple',
}}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
);
};
And then in the component's render function, I call it:
render() {
return (
<div>
{this.selectRenderer()}
<p>Value:</p>{this.state.age}
</div>
);
}
This works. (and thus I'll mark it answered in two days)
I am curious, however, WHY this particular chunk of JSX needs to be brought in as a function whereas other chunks of JSX do not. (specifically, a material-ui text field works just fine being assigned to state as I did in the OP) I'd like to be able to build out this question once (preferably as part of the componentDidMount lifecycle) and then pass the built-out question somehow to the render function. State seems to be the way to do that, but I can't with Select/MenuItems for some reason.

Resources