質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.54%

React+ReduxにおけるMaterial-UI

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 259

khkhkh

score 15

前提・実現したいこと

React+Redux+Material-UIを用いて簡単なアプリケーションを作成しています。
Material-UIのDrawerのopen,closeをReduxで管理しているのですが、ボタンを押しても一向に開いてくれません。
どなたか解決方法のご教授をお願い致します。

該当のソースコード

/**
 * components/Header.js
 */
const drawerWidth = 200 // Width for Drawer

const styles = theme => ({
    root: {
        flexGrow: 1,
        zIndex: 1,
        overflow: 'hidden',
        position: 'relative',
        display: 'flex',
        width: '100%',
    },
    appBar: {
        position: 'absolute',
        marginLeft: drawerWidth,
        [theme.breakpoints.up('md')]: {
            width: `calc(100% - ${drawerWidth}px)`,
        },
    },
    toolbar: theme.mixins.toolbar,
    navIconHide: {
        [theme.breakpoints.up('md')]: {
            display: 'none',
        },
    },
    drawerPaper: {
        width: drawerWidth,
        [theme.breakpoints.up('md')]: {
            position: 'relative',
        },
    },
    drawerListSubheader: {
        backgroundColor: theme.palette.background.paper,
    },
    content: {
        flexGrow: 1,
        overflowY: 'scroll',
        backgroundColor: theme.palette.background.default,
        padding: theme.spacing(3),
    },
})

class Main extends React.Component {
    render() {
        const { classes, theme } = this.props

        const drawer = (
            <div>
                <List>
                    <ListSubheader className={classes.drawerListSubheader} component="div">First List</ListSubheader>
                    <ListItem button>
                        <ListItemText primary="First List Button" />
                    </ListItem>
                </List>
                <Divider />
                <List>
                    <ListSubheader className={classes.drawerListSubheader} component="div">Second List</ListSubheader>
                    <ListItem button>
                        <ListItemText primary="Second List Button" />
                    </ListItem>
                </List>
            </div>
        )

        return (
            <div className={classes.root}>
                <AppBar className={classes.appBar}>
                    <Toolbar>
                        <IconButton
                            color="inherit" // アイコンの色
                            aria-label="open drawer" // ラベル付け
                            onClick={() => this.props.handleToggleDrawer()}
                            className={classes.navIconHide}
                        >
                            <MenuIcon />    {/* メニューアイコン */}
                        </IconButton>
                        <Typography color="inherit" noWrap>
                            Suggesh
                        </Typography>
                    </Toolbar>
                </AppBar>
                <Hidden mdUp> {/* md未満 */}
                    <Drawer
                        variant="temporary"
                        anchor={theme.direction === 'rtl' ? 'right' : 'left'}
                        open={this.props.mobileOpen}
                        onClose={() => this.props.handleToggleDrawer()}
                        classes={{
                            paper: classes.drawerPaper,
                        }}
                        ModalProps={{
                            keepMounted: true, // Better open performance on mobile.
                        }}
                    >
                        {drawer}
                    </Drawer>
                </Hidden>
                <Hidden smDown implementation="css"> {/* md以上 */}
                    <Drawer
                        variant="permanent"
                        open
                        classes={{
                            paper: classes.drawerPaper,
                        }}
                    >
                        {drawer}
                    </Drawer>
                </Hidden>
                <main className={classes.content}>
                    <div className={classes.toolbar} />
                    <h1>Hello World</h1>
                </main>
            </div>
        )
    }
}

Main.propTypes = {
    classes: PropTypes.object.isRequired,
    theme: PropTypes.object.isRequired,
}

export default withStyles(styles, { withTheme: true })(Main)



/**
 * containers/HeaderContainer.js
/*
import { connect } from 'react-redux';
import Header from '../components/Header'
import { toggleDrawer } from '../actions/HeaderActions'

const mapStateToProps = state => ({
    mobileOpen: state.mobileOpen
})

const mapDispatchToProps = dispatch => ({
    handleToggleDrawer: () => dispatch(toggleDrawer())
})

export default connect(mapStateToProps, mapDispatchToProps)(Header)



/**
 * reducers/HeaderDrawerReducer.js
/*
import * as actionTypes from '../utils/actionTypes'

const initialState = {
    mobileOpen: false,
}

export default function HeaderDrawerReducer(state = initialState, action) {
    switch (action.type) {
        case actionTypes.TOGGLE_DRAWER:
            console.log('mobileOpen: ' + !state.mobileOpen)
            return Object.assign({}, state, {
                mobileOpen: !state.mobileOpen,
            })
        default:
            return state
    }
}



/**
 * reducers/index.js
/*
import { combineReducers } from 'redux';
import HeaderDrawerReducer from './HeaderDrawerReducer';

const reducers = combineReducers({
    HeaderDrawerReducer: HeaderDrawerReducer,
});

export default reducers;



/**
 * utils/actionTypes.js
 */
export const TOGGLE_DRAWER = 'TOGGLE_DRAWER';


**ーーー追記ーーー**
/**
 * actions/HeaderActions.js
 */
import { TOGGLE_DRAWER } from "../utils/actionTypes";

export function toggleDrawer(){
    return {
        type: TOGGLE_DRAWER
    }
}


/**
 * App.js
 */
import React from 'react';
import CssBaseline from '@material-ui/core/CssBaseline';
import {createStore} from 'redux';
import {Provider} from 'react-redux';
import HeaderContainer from './containers/HeaderContainer';
import reducers from './reducers/index';

const store = createStore(reducers)

function App() {
    return (
        <Provider store={store}>
            <CssBaseline>
                <HeaderContainer />
            </CssBaseline>
        </Provider>
    );
}

export default App;



/**
 * index.js
 */
import React from 'react'
import ReactDOM from 'react-dom'

import App from './App'

ReactDOM.render(
    <App />,
    document.getElementById('root')
)

試したこと

エラーはありません。
また、コンソールにはしっかりmobileOpenの値が出力されています。

ーー追記ーー
App.js で reducers/index.js を読み込むのをやめて、直接reducers/HeaderDrawerReducers を読み込めば適切に動作しました。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • jun68ykt

    2019/09/07 22:05

    こんにちは

    (1) actions/HeaderActions.js の内容(アクションクリエータが書かれているものと思いますが。)も、質問に追記して頂きたいです。

    (2) HeaderContainerの動作確認としては、HeaderContainer.js から export しているコンポーネントを たとえば App として、 index.js で

    import App from 'containers/HeaderContainer'

    ReactDOM.render(
    <Provider store={store}>
    <App />
    </Provider>, document.getElementById('root'));

    といった感じでしょうか? index.js で何か特別なことをやっていれば、 index.js も追記頂ければと思います。

    キャンセル

  • khkhkh

    2019/09/07 22:28 編集

    こんにちは!ご回答ありがとうございます!追記致しました!
    その後、「試したこと」にも追記致しましたが、App.js で reducers/index.js を読み込むのをやめて、直接reducers/HeaderDrawerReducers を読み込めば適切に動作しました。
    今後Reducerが増えることを予測してreducers/index.jsでcombineReducersしていたのですが、それがよくなかったのでしょうか。Reducer一つではcombineReducersはうまく動かないのでしょうか?

    キャンセル

  • jun68ykt

    2019/09/07 22:33

    追記ありがとうございます。 追記頂いたのですが、追記頂いた部分が原因ではなさそうでした。申し訳ないです。こうすればうまくいくのでは?と思われた部分を回答しました。

    キャンセル

回答 1

checkベストアンサー

0

こんにちは

以下のように combineReducers しているので、

const reducers = combineReducers({
    HeaderDrawerReducer: HeaderDrawerReducer,
});


下記の部分

修正前:

const mapStateToProps = state => ({
    mobileOpen: state.mobileOpen
})


を、以下に修正する必要がまずあるかなと思います。

修正後:

const mapStateToProps = state => ({
    mobileOpen: state.HeaderDrawerReducer.mobileOpen
})

ご質問の ーー追記ーー を読むと、上記の修正だけで意図通り動くかもしれません。

以上参考になれば幸いです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/09/07 22:34

    修正したところ正しく動作しました!お忙しい中ありがとうございました!

    キャンセル

  • 2019/09/07 22:37

    どういたしまして。
    > 正しく動作しました!
    とのことでよかったです👏
    combineReducersを使って複数のリデューサーを束ねたときに、state の構造がどうなるかについては

    https://redux.js.org/api/combinereducers#combinereducersreducers

    の一番上に出ている例が分かりやすいです。

    キャンセル

  • 2019/09/08 01:00

    ありがとうございます!上記のサイトで勉強させてもらいます!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.54%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる