はじめに
React + Redux + Material-UI で簡単なアプリケーションを開発しています。
現在はMaterial-UIのDrawerを実装しているのですが、
connect()でComponentに渡した関数を使用すると下記のようなエラーが発生します。
どなたかご教授お願い致します。
発生している問題・エラーメッセージ
TypeError: this.props.handleToggleDrawer is not a function onClick src/components/header/NavIcon.js:79 76 | <IconButton 77 | color="inherit" 78 | aria-label="Menu" > 79 | onClick={() => this.props.handleToggleDrawer()} 80 | ^ className={classes.navIcon} 81 | > 82 | <MenuIcon />
該当のソースコード
actions/NavIconAction
1/** 2 * action/NavIconAction.js 3 */ 4import { TOGGLE_DRAWER } from "../utils/actionTypes"; 5 6export const toggleDrawer = () => { 7 return { 8 type: TOGGLE_DRAWER, 9 } 10}
reducer
1/** 2 * reducers/NavIconReducer.js 3 */ 4import * as actionTypes from '../utils/actionTypes' 5 6const initialState = { 7 open: false, 8} 9 10export default function NavIconReducer(state = initialState, action) { 11 switch (action.type) { 12 case actionTypes.TOGGLE_DRAWER: 13 console.log('open: ' + !state.open) 14 return Object.assign({}, state, { 15 open: !state.open, 16 }) 17 default: 18 return state 19 } 20}
reducer/index.js
1/** 2 * reducers/index.js 3 */ 4import { combineReducers } from 'redux'; 5import NavIconReducer from './NavIconReducer'; 6import ShareIconReducer from './ShareIconReducer'; 7import NotificationReducer from './NotificationReducer'; 8 9const reducers = combineReducers({ 10 NavIconReducer, 11 ShareIconReducer, 12 NotificationReducer 13}); 14 15export default reducers;
container
1/** 2 * containers/NavIconContainer.js 3 */ 4import { connect } from 'react-redux'; 5import { toggleDrawer } from '../actions/NavIconAction' 6import NavIcon from '../components/header/NavIcon' 7 8const mapStateToProps = state => ({ 9 open: state.NavIconReducer.open, 10}) 11 12const mapDispatchToProps = dispatch => { 13 return{ 14 handleToggleDrawer: () => dispatch(toggleDrawer()) 15 } 16} 17 18export default connect(mapStateToProps, mapDispatchToProps)(NavIcon)
component
1/** 2 * components/header/NavIcon.js 3 */ 4import React from 'react' 5import { withStyles } from '@material-ui/core/styles' 6import MenuIcon from '@material-ui/icons/Menu' 7import Hidden from '@material-ui/core/Hidden' 8import Drawer from '@material-ui/core/Drawer' 9import Divider from '@material-ui/core/Divider' 10import List from '@material-ui/core/List' 11import ListItem from '@material-ui/core/ListItem' 12import ListItemText from '@material-ui/core/ListItemText' 13import InfoIcon from '@material-ui/icons/Info'; 14import HomeIcon from '@material-ui/icons/Home'; 15import AccountCircle from '@material-ui/icons/AccountCircle'; 16import LockOpen from '@material-ui/icons/LockOpen'; 17import HowToReg from '@material-ui/icons/HowToReg'; 18import { ListItemIcon } from '@material-ui/core'; 19import IconButton from '@material-ui/core/IconButton'; 20 21const drawerWidth = 250 // Width for Drawer 22 23const styles = theme => ({ 24 navIcon: { 25 [theme.breakpoints.up('md')]: { 26 display: 'none', 27 }, 28 }, 29 drawer: { 30 }, 31 drawerPaper: { 32 width: drawerWidth, 33 }, 34}); 35 36class NavIcon extends React.Component { 37 render() { 38 const { theme, classes } = this.props 39 40 const drawer = ( 41 <div> 42 <Divider /> 43 <List> 44 <ListItem button> 45 <ListItemIcon><InfoIcon /></ListItemIcon> 46 <ListItemText primary="***** とは" /> 47 </ListItem> 48 </List> 49 <Divider /> 50 <List> 51 <ListItem button> 52 <ListItemIcon><HomeIcon /></ListItemIcon> 53 <ListItemText primary="トップページ" /> 54 </ListItem> 55 </List> 56 <List> 57 <ListItem button> 58 <ListItemIcon><AccountCircle /></ListItemIcon> 59 <ListItemText primary="マイページ" /> 60 </ListItem> 61 </List> 62 <List> 63 <ListItem button> 64 <ListItemIcon><LockOpen /></ListItemIcon> 65 <ListItemText primary="ログイン" /> 66 </ListItem> 67 </List> 68 <List> 69 <ListItem button> 70 <ListItemIcon><HowToReg /></ListItemIcon> 71 <ListItemText primary="新規会員登録" /> 72 </ListItem> 73 </List> 74 </div> 75 ) 76 77 return ( 78 <div> 79 <IconButton 80 color="inherit" 81 aria-label="Menu" 82 onClick={() => this.props.handleToggleDrawer()} 83 className={classes.navIcon} 84 > 85 <MenuIcon /> 86 </IconButton> 87 <nav className={classes.drawer} aria-label="link"> 88 <Hidden mdUp> {/* md未満 */} 89 <Drawer 90 variant="temporary" 91 anchor={theme.direction === 'rtl' ? 'right' : 'left'} 92 open={this.props.open} 93 onClose={() => this.props.handleToggleDrawer()} 94 classes={{ 95 paper: classes.drawerPaper, 96 }} 97 ModalProps={{ 98 keepMounted: true, // Better open performance on mobile. 99 }} 100 > 101 {drawer} 102 </Drawer> 103 </Hidden> 104 <Hidden smDown implementation="css"> {/* md以上 */} 105 <Drawer 106 variant="permanent" 107 open 108 classes={{ 109 paper: classes.drawerPaper, 110 }} 111 > 112 {drawer} 113 </Drawer> 114 </Hidden> 115 </nav> 116 </div> 117 ) 118 } 119} 120 121export default withStyles(styles, { withTheme: true })(NavIcon)
/** * components/header/index.js */ import React from 'react' import { withStyles } from '@material-ui/core/styles' import AppBar from '@material-ui/core/AppBar' import Toolbar from '@material-ui/core/ToolBar' import Typography from '@material-ui/core/Typography'; import NavIcon from './NavIcon' import ShareIcon from './ShareIcon' import logo from '../../logo.png' const drawerWidth = 250 // Width for Drawer const styles = theme => ({ appBar: { width: '100%', marginLeft: drawerWidth, [theme.breakpoints.up('md')]: { width: `calc(100% - ${drawerWidth}px)`, }, }, toolBar: { }, title: { margin: 'auto', }, logo: { width: 20, paddingRight: 5, }, }) const Header = ({ classes }) => ( <div className={classes.header}> <AppBar className={classes.appBar}> <Toolbar className={classes.toolBar}> <NavIcon /> <Typography className={classes.title}> <img src={logo} alt="Header logo" className={classes.logo} /> ぐるめなう </Typography> </Toolbar> </AppBar> </div> ) export default withStyles(styles, { withTheme: true })(Header)
App
1/** 2 * App.js 3 */ 4import React from 'react'; 5import { Route, Switch } from 'react-router-dom' 6import { makeStyles } from '@material-ui/core/styles' 7import CssBaseline from '@material-ui/core/CssBaseline' 8import Header from './components/header' 9import About from './components/about' 10import Top from './components/top' 11import MyPage from './components/mypage' 12import Login from './components/login' 13import Signup from './components/signup' 14 15const useStyles = makeStyles(() => ({ 16 root: { 17 }, 18})) 19 20function App() { 21 const classes = useStyles(); 22 23 return ( 24 <CssBaseline> 25 <div className={classes.root}> 26 <Header /> 27 <Switch> 28 <Route exact path="/" component={Top} /> 29 <Route exact path="/mypage" component={MyPage} /> 30 <Route exact path="/login" component={Login} /> 31 <Route exact path="/signup" component={Signup} /> 32 <Route exact path="/about" component={About} /> 33 </Switch> 34 </div> 35 </CssBaseline> 36 ); 37} 38 39export default App;
index.js
1/** 2 * index.js 3 */ 4import React from 'react' 5import ReactDOM from 'react-dom' 6import { Provider } from 'react-redux'; 7import App from './App' 8import { createStore } from 'redux'; 9import reducers from './reducers'; 10 11const store = createStore(reducers) 12 13ReactDOM.render( 14 <Provider store={store}> 15 <App /> 16 </Provider>, 17 document.getElementById('root') 18)
試したこと
MenuIconをクリックすると上記のエラーが発生します。
回答1件
あなたの回答
tips
プレビュー