У новичка в React возникли проблемы с адаптацией примера Material-UI к проекту React. Штат не работает так же, как крючки - PullRequest
0 голосов
/ 19 июня 2019

Я все еще новичок в React, но я пытаюсь создать форму для веб-приложения управления проектами.

Я использую Material-UI.Я основал свой код на одном из примеров компонентов блока выбора из документов material-ui.

Я только недавно выяснил, как работают React-Hooks, и в примере использовалась эта функция.

Я пытаюсь изменить form.js, чтобы обновить окно множественного выбора, основываясь на состоянии App.js через реквизиты, вместо того, чтобы полагаться на хуки функциональных компонентов.

Кажется,работать, когда я оставляю ловушки на месте для personName, но как только я пытаюсь изменить его на что-то вроде props.accountSelected, я начинаю видеть ошибки, и несколько выбранных чипов больше не отображаются.

App.js:

import React, { Component } from 'react';
import './App.css';
import Form from './Form'

class App extends Component {
constructor() {
  super();
  this.state = {
      projectName: '',
      accountField: {
        selected: {value: 'jacks', label: 'Jacks'},
        options:[
          {value: 'walmart', label: 'Walmart'},
          {value: 'zellers', label: 'Zellers'},
          {value: 'partyplace', label: 'Party Place'},
          {value: 'majorbank', label: 'Major bank'}
        ]
      }
  }
}

setAccountsSelected(selected) {
  console.log('>> [App.js] (setAccountsSelected) ',selected)
}

render() {
  return (
    <div className="App">
      <Form 
        accountFieldoptions={this.state.accountField.options}
        setAccountsSelected={this.setAccountsSelected}
        accountSelected={this.state.accountField.selected}
      />
    </div>
  );

  }
}
export default App;

Form.js (работает, но выбранные фишки больше не отображаются)

import React from 'react';
//import Select from 'react-select'; // https://github.com/JedWatson/react-select
import { makeStyles, useTheme } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
import Input from '@material-ui/core/Input';
import InputLabel from '@material-ui/core/InputLabel';
import MenuItem from '@material-ui/core/MenuItem';
import FormControl from '@material-ui/core/FormControl';
import TextField from '@material-ui/core/TextField';
import Select from '@material-ui/core/Select';
import Chip from '@material-ui/core/Chip';

const useStyles = makeStyles(theme => ({
  root: {
    display: 'flex',
    flexWrap: 'wrap',
  },
  formControl: {
    margin: theme.spacing(1),
    minWidth: 120,
    maxWidth: 300,
  },
  chips: {
    display: 'flex',
    flexWrap: 'wrap',
  },
  chip: {
    margin: 2,
  },
  noLabel: {
    marginTop: theme.spacing(3),
  },
}));


const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
  PaperProps: {
    style: {
      maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
      width: 250,
    },
  },
};

let names = [
  'Oliver Hansen',
  'Van Henry',
  'April Tucker',
  'Ralph Hubbard',
  'Omar Alexander',
  'Carlos Abbott',
  'Miriam Wagner',
  'Bradley Wilkerson',
  'Virginia Andrews',
  'Kelly Snyder',
];

function getStyles(name, personName, theme) {
  return {
    fontWeight:
      personName.indexOf(name) === -1
        ? theme.typography.fontWeightRegular
        : theme.typography.fontWeightMedium,
  };
}



export default function Form(props) {
  console.log('>> [Form.js] props = ',props)

  const classes = useStyles();
  const theme = useTheme();

  names = [...props.accountFieldoptions];

  console.log('>> [Form.js] names = ', names)

  const [personName, setPersonName] = React.useState([]);

  function handleChange(event) {
    //setPersonName(event.target.value);
    props.setAccountsSelected(event.target.value);
  }

  // function handleChangeMultiple(event) {
  //   const { options } = event.target;
  //   const value = [];
  //   for (let i = 0, l = options.length; i < l; i += 1) {
  //     if (options[i].selected) {
  //       value.push(options[i].value);
  //     }
  //   }
  //   setPersonName(value);

  // }

  return (
    <div className={classes.root}>
      <FormControl className={classes.formControl}>
        <InputLabel htmlFor="select-multiple-accounts">Account</InputLabel>
        <Select
          multiple
          value={personName}
          onChange={handleChange}
          input={<Input id="select-multiple-accounts" />}
          renderValue={selected => (
            <div className={classes.chips}>
              {selected.map(value => (
                <Chip key={value} label={value} className={classes.chip} />
              ))}
            </div>
          )}
          MenuProps={MenuProps}
        >
          {names.map(name => (
            <MenuItem key={name.label} value={name.label} style={getStyles(name.label, personName, theme)}>
              {name.label}
            </MenuItem>
          ))}
        </Select>
      </FormControl>

    </div>
  );
}

Form.js (выдает ошибку: TypeError: personName.indexOf не является функцией getStyles src/Form.js:62)

import React from 'react';
//import Select from 'react-select'; // https://github.com/JedWatson/react-select
import { makeStyles, useTheme } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
import Input from '@material-ui/core/Input';
import InputLabel from '@material-ui/core/InputLabel';
import MenuItem from '@material-ui/core/MenuItem';
import FormControl from '@material-ui/core/FormControl';
import TextField from '@material-ui/core/TextField';
import Select from '@material-ui/core/Select';
import Chip from '@material-ui/core/Chip';

const useStyles = makeStyles(theme => ({
  root: {
    display: 'flex',
    flexWrap: 'wrap',
  },
  formControl: {
    margin: theme.spacing(1),
    minWidth: 120,
    maxWidth: 300,
  },
  chips: {
    display: 'flex',
    flexWrap: 'wrap',
  },
  chip: {
    margin: 2,
  },
  noLabel: {
    marginTop: theme.spacing(3),
  },
}));


const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
  PaperProps: {
    style: {
      maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
      width: 250,
    },
  },
};

let names = [
  'Oliver Hansen',
  'Van Henry',
  'April Tucker',
  'Ralph Hubbard',
  'Omar Alexander',
  'Carlos Abbott',
  'Miriam Wagner',
  'Bradley Wilkerson',
  'Virginia Andrews',
  'Kelly Snyder',
];

function getStyles(name, personName, theme) {
  return {
    fontWeight:
      personName.indexOf(name) === -1
        ? theme.typography.fontWeightRegular
        : theme.typography.fontWeightMedium,
  };
}



export default function Form(props) {
  console.log('>> [Form.js] props = ',props)

  const classes = useStyles();
  const theme = useTheme();

  names = [...props.accountFieldoptions];

  console.log('>> [Form.js] names = ', names)

  const [personName, setPersonName] = React.useState([]);

  function handleChange(event) {
    //setPersonName(event.target.value);
    props.setAccountsSelected(event.target.value);
  }

  // function handleChangeMultiple(event) {
  //   const { options } = event.target;
  //   const value = [];
  //   for (let i = 0, l = options.length; i < l; i += 1) {
  //     if (options[i].selected) {
  //       value.push(options[i].value);
  //     }
  //   }
  //   setPersonName(value);

  // }

  return (
    <div className={classes.root}>
      <FormControl className={classes.formControl}>
        <InputLabel htmlFor="select-multiple-accounts">Account</InputLabel>
        <Select
          multiple
          value={props.accountSelected}
          onChange={handleChange}
          input={<Input id="select-multiple-accounts" />}
          renderValue={selected => (
            <div className={classes.chips}>
              {selected.map(value => (
                <Chip key={value} label={value} className={classes.chip} />
              ))}
            </div>
          )}
          MenuProps={MenuProps}
        >
          {names.map(name => (
            <MenuItem key={name.label} value={name.label} style={getStyles(name.label, props.accountSelected, theme)}>
              {name.label}
            </MenuItem>
          ))}
        </Select>
      </FormControl>

    </div>
  );
}

Исходный пример Я основал свой код на:

https://material -ui.com / components / selects /

import React from 'react';
import clsx from 'clsx';
import { makeStyles, useTheme } from '@material-ui/core/styles';
import Input from '@material-ui/core/Input';
import InputLabel from '@material-ui/core/InputLabel';
import MenuItem from '@material-ui/core/MenuItem';
import FormControl from '@material-ui/core/FormControl';
import ListItemText from '@material-ui/core/ListItemText';
import Select from '@material-ui/core/Select';
import Checkbox from '@material-ui/core/Checkbox';
import Chip from '@material-ui/core/Chip';

const useStyles = makeStyles(theme => ({
  root: {
    display: 'flex',
    flexWrap: 'wrap',
  },
  formControl: {
    margin: theme.spacing(1),
    minWidth: 120,
    maxWidth: 300,
  },
  chips: {
    display: 'flex',
    flexWrap: 'wrap',
  },
  chip: {
    margin: 2,
  },
  noLabel: {
    marginTop: theme.spacing(3),
  },
}));

const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
  PaperProps: {
    style: {
      maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
      width: 250,
    },
  },
};

const names = [
  'Oliver Hansen',
  'Van Henry',
  'April Tucker',
  'Ralph Hubbard',
  'Omar Alexander',
  'Carlos Abbott',
  'Miriam Wagner',
  'Bradley Wilkerson',
  'Virginia Andrews',
  'Kelly Snyder',
];

function getStyles(name, personName, theme) {
  return {
    fontWeight:
      personName.indexOf(name) === -1
        ? theme.typography.fontWeightRegular
        : theme.typography.fontWeightMedium,
  };
}

export default function MultipleSelect() {
  const classes = useStyles();
  const theme = useTheme();
  const [personName, setPersonName] = React.useState([]);

  function handleChange(event) {
    setPersonName(event.target.value);
  }

  function handleChangeMultiple(event) {
    const { options } = event.target;
    const value = [];
    for (let i = 0, l = options.length; i < l; i += 1) {
      if (options[i].selected) {
        value.push(options[i].value);
      }
    }
    setPersonName(value);
  }

  return (
    <div className={classes.root}>
      <FormControl className={classes.formControl}>
        <InputLabel htmlFor="select-multiple">Name</InputLabel>
        <Select
          multiple
          value={personName}
          onChange={handleChange}
          input={<Input id="select-multiple" />}
          MenuProps={MenuProps}
        >
          {names.map(name => (
            <MenuItem key={name} value={name} style={getStyles(name, personName, theme)}>
              {name}
            </MenuItem>
          ))}
        </Select>
      </FormControl>
      <FormControl className={classes.formControl}>
        <InputLabel htmlFor="select-multiple-checkbox">Tag</InputLabel>
        <Select
          multiple
          value={personName}
          onChange={handleChange}
          input={<Input id="select-multiple-checkbox" />}
          renderValue={selected => selected.join(', ')}
          MenuProps={MenuProps}
        >
          {names.map(name => (
            <MenuItem key={name} value={name}>
              <Checkbox checked={personName.indexOf(name) > -1} />
              <ListItemText primary={name} />
            </MenuItem>
          ))}
        </Select>
      </FormControl>
      <FormControl className={classes.formControl}>
        <InputLabel htmlFor="select-multiple-chip">Chip</InputLabel>
        <Select
          multiple
          value={personName}
          onChange={handleChange}
          input={<Input id="select-multiple-chip" />}
          renderValue={selected => (
            <div className={classes.chips}>
              {selected.map(value => (
                <Chip key={value} label={value} className={classes.chip} />
              ))}
            </div>
          )}
          MenuProps={MenuProps}
        >
          {names.map(name => (
            <MenuItem key={name} value={name} style={getStyles(name, personName, theme)}>
              {name}
            </MenuItem>
          ))}
        </Select>
      </FormControl>
      <FormControl className={clsx(classes.formControl, classes.noLabel)}>
        <Select
          multiple
          displayEmpty
          value={personName}
          onChange={handleChange}
          input={<Input id="select-multiple-placeholder" />}
          renderValue={selected => {
            if (selected.length === 0) {
              return <em>Placeholder</em>;
            }

            return selected.join(', ');
          }}
          MenuProps={MenuProps}
        >
          <MenuItem disabled value="">
            <em>Placeholder</em>
          </MenuItem>
          {names.map(name => (
            <MenuItem key={name} value={name} style={getStyles(name, personName, theme)}>
              {name}
            </MenuItem>
          ))}
        </Select>
      </FormControl>
      <FormControl className={classes.formControl}>
        <InputLabel shrink htmlFor="select-multiple-native">
          Native
        </InputLabel>
        <Select
          multiple
          native
          value={personName}
          onChange={handleChangeMultiple}
          inputProps={{
            id: 'select-multiple-native',
          }}
        >
          {names.map(name => (
            <option key={name} value={name}>
              {name}
            </option>
          ))}
        </Select>
      </FormControl>
    </div>
  );
}

Может кто-нибудь объяснить мне, что я делаю неправильно, и почему это работает с крючками, но не с реквизитом?

1 Ответ

1 голос
/ 20 июня 2019

Я думаю, вам нужно передать массив selected в множественном выборе пользовательского интерфейса материала.

Пример пользовательского интерфейса для материала объявил personName как массив в хуке useState здесь:

  const [personName, setPersonName] = React.useState([]);

Может быть, вы можете попробовать изменить состояние выбранного приложения на массив, как показано ниже, и посмотрите, поможет ли это:

this.state = {
      projectName: "",
      accountField: {
        // selected: { value: "jacks", label: "Jacks" },
        selected: ["jacks"],
        options: [
          { value: "walmart", label: "Walmart" },
          { value: "zellers", label: "Zellers" },
          { value: "partyplace", label: "Party Place" },
          { value: "majorbank", label: "Major bank" }
        ]
      }
    };
...