大和ノ畢生載録

ヤマトノヒッセイサイロク

【React】MaterialUIのselectコンポーネントがonChangeで変更されない

はじめに

こんにちは!

私は,学生開発チーム「Nineteen」(@nineteen_team)でシフト作成アプリを開発に携わっているのですが,開発するにあたって遭遇した問題点,解決策を,備忘録も兼ねて今日から書いていきたいと思います。

Nineteenで開発しているシフト作成アプリに関してはまたの機会に詳しく記事にしようと思います。

私自身プログラミング初学者のため,誤った表現をしてしまうなど,全体的にわかりづらい記事になってしまうことを予めご承知おきください。

結論

結論から先にお伝えしますと,Selectコンポーネントの「value」というpropsを「defaultValue」に書き換えることにより解決しました。

問題点

ReactとMaterialUIで作成した以下のような画面で,ドロップダウンメニューからアイテムを選択しても反映されない問題に遭遇しました。

このようにホールや未設定を押しても反映されません,,,

このメニューからアイテムを選択すると,setStateで「rows」というstateの「position」が変更されるようになっています。stateは以下のようになっています。

//positon 0が"未設定",1が"厨房",2が"ホール"
 const [rows, setRows] = React.useState([
    {id:0,name:"0太郎",position:1,color:'#00ff00'},
    {id:1,name:"1太郎",position:2,color:'#00ff00'},
  ]);

また,コンポーネントは以下のようになっています。

<TableContainer component={Paper} sx={{ minWidth: 550 }}>
  <Table aria-label="simple table">
    <TableHead>
      <TableRow>
        <TableCell align="left"><b>名前</b></TableCell>
        <TableCell align="left"><b>ポジション名</b></TableCell>
        <TableCell align="left"><b></b></TableCell>
      </TableRow>
    </TableHead>
    <TableBody>
      {rows.map((row, index) => (
        <TableRow
          key={row.id}
          sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
        >
          <TableCell component="th" scope="row" align="left">
            <font size="5">{row.name}</font>
          </TableCell>
          <TableCell align="left">
            <FormControl variant="standard" sx={{ mt: 1, mb: 1, minWidth: 120 }}>
              <InputLabel id="demo-simple-select-standard-label"></InputLabel>
              <Select
                labelId="demo-simple-select-standard-label"
                id="demo-simple-select-standard"
                value={row.position}
                onChange={(event) => {
                  let newState = rows;
                  newState[index].position = event.target.value;
                  setRows(newState);
                }}
                label="ポジション"
              >
                {pos.map((po) => {
                  return (
                    <MenuItem value={po.id} key={po.id}>{po.name}</MenuItem>
                  )
                })}

              </Select>
            </FormControl>

          </TableCell>
          <TableCell align="left"><Typography variant="h4" style={{ color: row.color }}></Typography></TableCell>
        </TableRow>
      ))}
    </TableBody>
  </Table>
</TableContainer>

解決策

2時間ほど格闘した結果,以下のように修正することで解決しました。

修正前
<Select
  labelId="demo-simple-select-standard-label"
  id="demo-simple-select-standard"
  value={row.position} //変更したところ
   onChange={(event) => {
     let newState = rows;
     console.log(newState[index]);
     newState[index].position = event.target.value;
     setRows(newState);
   }
   label="ポジション"
>
修正後
<Select
  labelId="demo-simple-select-standard-label"
  id="demo-simple-select-standard"
  defaultValue={row.position} //変更したところ
  onChange={(event) => {
    let newState = rows;
    console.log(newState[index]);
    newState[index].position = event.target.value;
    setRows(newState);
  }
  label="ポジション"
>

Selectコンポーネントの「value」というpropsを「defaultValue」に書き換えることにより解決しました。


このようにしっかりと動作するようになりました!

参考サイト

stackoverflow.com