简体   繁体   中英

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM