yucatio@システムエンジニア

趣味で作ったものいろいろ

Material-UIのMenuを使用する(STEP 4 : Material-UIの導入 - React + Redux + Firebase チュートリアル)

★前回の記事

yucatio.hatenablog.com

ログアウトのボタンの常時表示をやめ、ユーザ名がクリックされた時にログアウトメニューが出るように変更します。Material-UIのMenuを使用します。

f:id:yucatio:20190428224042p:plain

Loginコンポーネントの内部stateにanchor(アンカー:ここではメニューの表示対象)を持つので、関数コンポーネントからReact.Componentをを拡張したクラスへと変更します。

公式のMenuのデモを参考に変更していきます。

src/components/header/Login.js({/* xxx */}のコメントは実行前に削除してください)

import { compose } from 'redux'  // 追加
import { withStyles } from '@material-ui/core/styles'  // 追加
import Menu from '@material-ui/core/Menu'  // 追加
import MenuItem from '@material-ui/core/MenuItem'  // 追加

// stylesを追加
const styles = {
  noTransform: {
    textTransform: 'none',  // #1
  },
}

// 関数コンポーネントからReact.Componentを拡張したクラスに変更
class Login extends React.Component {
  state = {
    anchorEl: null,  // #2
  }

  handleClick = event => {  // #3
    this.setState({ anchorEl: event.currentTarget })
  }

  handleClose = () => {  // #4
    this.setState({ anchorEl: null })
  }

  render() {
    const { auth, loginWithGoogle, logout, classes } = this.props   // classesを追加
    const { anchorEl } = this.state

    if (!isLoaded(auth)) {
      return <CircularProgress color="inherit" />
    }
    if (isEmpty(auth)) {
      return (
        <Button variant="contained" color="primary" onClick={loginWithGoogle} className={classes.noTransform}>Googleアカウントでログイン</Button>  {/* classNameを追加 */}
      )
    }
    return (
      <React.Fragment>
        <Button color="inherit" aria-owns={anchorEl ? 'user-menu' : undefined} aria-haspopup="true"
          onClick={this.handleClick} className={classes.noTransform}>  {/* #5 */}
          {auth.displayName} さん
        </Button>
        <Menu  // #6
            id="user-menu"
            anchorEl={anchorEl}
            open={Boolean(anchorEl)}
            onClose={this.handleClose}
        >
          <MenuItem onClick={logout}>ログアウト</MenuItem>  {/* #7 */}
        </Menu>
      </React.Fragment>
    )
  }
}

Login.propTypes = {
  // 略
  classes: PropTypes.object.isRequired,  // 追加
}

// 略

// composeを使用してwithStylesとconnectを合成するように変更
export default compose(
  withStyles(styles),
  connect(
    mapStateToProps,
    mapDispatchToProps
))(Login)
  • Material-UIのボタンは、デフォルトでは全てのアルファベットは大文字に変換されます。小文字を小文字のまま表示したい場合はtextTransform: 'none'を指定します(#1)。
  • anchorElはメニューを表示する対象です。初期値はnullを設定します(#2)。
  • ユーザ名がクリックされた時の動作を定義します(#3)。anchorElにクリックされた要素を設定します。
  • メニューが閉じられる時の動作を定義します(#4)。anchorElnullを設定し、表示対象をなくします。
  • ユーザ名の表示({auth.displayName}さん)をButtonで囲みます(#5)。aria-ownsはメニュー要素のidを指定し、aria-haspopupはtrueを指定します。詳しくは参考のリンクを参照ください。
  • 公式のデモを参考にメニューの設定をします(#6)。anchorEl要素にstateanchorElを指定します。openanchorElが存在するかを指定しています。
  • メニューの各項目をMenuItemとして追加します(#7)。

実行結果です。ログアウトボタンは通常では見えません。

f:id:yucatio:20181209174215p:plain

ユーザ名をクリックするとログアウトメニューが表示されました。

f:id:yucatio:20181209174236p:plain

"ログアウト"をクリックすると正常にログアウトします。

f:id:yucatio:20181209174332p:plain

以上でMenuを使用してログアウトメニューを表示することができました。

参考

★次回の記事

yucatio.hatenablog.com

★目次

yucatio.hatenablog.com