MATERIAL-UIのMultiple SelectでChipから選択を解除する

#はじめに
React + Typescript + MaterialUIでフロントエンドを作成していたときに実現したいことができなかったので参考程度に投稿します。


##実現できなかった原因
Chipの×ボタンを押してもSelectのメニューが出てきてしまう

##実現したいこと
MaterialUIの公式ドキュメントに書かれていた「[Multiple Select](https://material-ui.com/components/selects/#multiple-select)(Chip)」でChipの×ボタンからも選択を解除したい！
![last.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649992/ac949482-f666-a4cf-818b-bb90520def46.gif)


#結論
Chipコンポーネントに以下プロパティを追加

```react
onMouseDown={(event) => {event.stopPropagation();}}
```

#前提条件
+ typescript,React,MaterialUiについてある程度の知識がある。
+ [create-react-app](https://create-react-app.dev/docs/adding-typescript/#getting-started-with-typescript-and-react)でアプリケーションが作成済み 

```
npx create-react-app {your_app_name} --template typescript
```

+ [material-ui](https://material-ui.com/getting-started/installation/)がインストール済み

```
npm install @material-ui/core
```

#Multiple SelectのChipを動かしてみる
まずは何も考えずコードをすべてコピーして```App.tsx```に貼り付ける。
次にChip以外のところは邪魔なのでChipに関連するものだけを残す。
そうするとコードは以下のようになります。

```react:App.tsx
import React from 'react';
import { createStyles, makeStyles, useTheme, Theme } 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 Select from '@material-ui/core/Select';
import Chip from '@material-ui/core/Chip';

const useStyles = makeStyles((theme: Theme) =>
  createStyles({
    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: string, personName: string[], theme: 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<string[]>([]);

  const handleChange = (event: React.ChangeEvent<{ value: unknown }>) => {
    setPersonName(event.target.value as string[]);
  };

  return (
    <div>
      <FormControl className={classes.formControl}>
        <InputLabel id="demo-mutiple-chip-label">Chip</InputLabel>
        <Select
          labelId="demo-mutiple-chip-label"
          id="demo-mutiple-chip"
          multiple
          value={personName}
          onChange={handleChange}
          input={<Input id="select-multiple-chip" />}
          renderValue={(selected) => (
            <div className={classes.chips}>
              {(selected as string[]).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>
    </div>
  );
}

```

そしてこれを```npm start```して```http://localhost:3000```でみると
![first.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649992/c394af91-8a2d-bc62-2fa1-5684bcb53654.gif)
よさそう！※拡大してます
#Chipの×ボタンを表示する
Chipに×ボタンを表示するにはChipコンポーネントに```onDelete```プロパティを追加すればいい。

```react:Apptsx
<Chip 
key={value} 
label={value} 
className={classes.chip} 
onDelete={() => { alert(value) }} /> #ここを追加
```

今回は×ボタンをがクリックされたことを確認するために、alertでクリックしたChipのラベルを表示するようにした。
そして再度```npm start```
![second.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649992/fcbf03e6-26f3-943e-985a-115bf69a2508.gif)

あれ...？何度押しても×ボタンがクリックできずにSelectのメニューが出てきてしまう。

#対処法
Chipコンポーネントに以下プロパティを追加

```react:App.tsx
<Chip 
  key={value} 
  label={value} 
  className={classes.chip} 
  onDelete={() => { alert(value) }}
  onMouseDown={(event) => {event.stopPropagation()}}  #ここを追加
/> 

```

そして再度```npm start```
![third.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649992/4b5a2055-28bc-8a31-99b6-82722f5af3ea.gif)

今度はきちんとクリックされてアラートが出ていますね。

#Chip削除の処理を追加する
先ほど入れたalertの処理をChip削除(personName内の名前を削除)する処理に変える。

新しく```chipDelete```という関数を用意する

```
 const chipDelete = (name: string) => {
    setPersonName(personName.filter(value => value !== name))
  }
```
そうすると```App.tsx```の```function MultipleSelect()```は以下のようになる

```react:App.tsx
export default function MultipleSelect() {
  const classes = useStyles();
  const theme = useTheme();
  const [personName, setPersonName] = React.useState<string[]>([]);

  const handleChange = (event: React.ChangeEvent<{ value: unknown }>) => {
    setPersonName(event.target.value as string[]);
  };
  const chipDelete = (name: string) => {
    setPersonName(personName.filter(value => value !== name))
  };

  return (
    <div>
      <FormControl className={classes.formControl}>
        <InputLabel id="demo-mutiple-chip-label">Chip</InputLabel>
        <Select
          labelId="demo-mutiple-chip-label"
          id="demo-mutiple-chip"
          multiple
          value={personName}
          onChange={handleChange}
          input={<Input id="select-multiple-chip" />}
          renderValue={(selected) => (
            <div className={classes.chips}>
              {(selected as string[]).map((value) => (
                <Chip
                  key={value} label={value} className={classes.chip}
                  onDelete={(event) => chipDelete(value)}
                  onMouseDown={(event) => { event.stopPropagation(); }}
                />
              ))}
            </div>
          )}
          MenuProps={MenuProps}
        >
          {names.map((name) => (
            <MenuItem key={name} value={name} style={getStyles(name, personName, theme)}>
              {name}
            </MenuItem>
          ))}
        </Select>
      </FormControl>
    </div>
  );
}
```
そして```npm start```
![last.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649992/005a80e4-90fa-944b-d70e-b83ce24c9fa0.gif)

うまくいった！！！！:v:

#終わりに
今思うとこんなにすっとできてしまうなんて。。。
ただ単にコピペするだけではなくてどのような処理が行われていて、どんなオプションのプロパティがあるのかを確認しないといけないですね。