🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Redux

Reduxは、JavaScriptアプリケーションの状態を管理するためのオープンソースライブラリです。ReactやAngularで一般的にユーザーインターフェイスの構築に利用されます。

Material-UI

Material-UIは、Material Designを利用可能なオープンソースのReact向けUIコンポーネントキットです。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

解決済

2回答

3425閲覧

「React」Material-UIのDialogをReduxで管理したい。

退会済みユーザー

退会済みユーザー

総合スコア0

Redux

Reduxは、JavaScriptアプリケーションの状態を管理するためのオープンソースライブラリです。ReactやAngularで一般的にユーザーインターフェイスの構築に利用されます。

Material-UI

Material-UIは、Material Designを利用可能なオープンソースのReact向けUIコンポーネントキットです。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

1クリップ

投稿2019/09/10 12:36

編集2019/09/10 12:41

前提・実現したいこと

Material-UIのDialogをReduxで管理したいのですが、中々思うような動作になりません。
具体的にはAction OPEN_SHARE_DIALOGでDialogをOpenし、Action CLOSE_SHARE_DIALOGでCloseしたいのですが、中々実装できません。
どなたかご教授のほど宜しくお願い致します。

該当のソースコード

JavaScript

1/** 2 * utils/actionTypes.js 3 */ 4略… 5export const OPEN_SHARE_DIALOG = 'OPEN_SHARE_DIALOG'; 6export const CLOSE_SHARE_DIALOG = 'CLOSE_SHARE_DIALOG'; 7 8 9/** 10 * actions/HeaderShareDialogAction.js 11 */ 12import { OPEN_SHARE_DIALOG } from "../utils/actionTypes"; 13import { CLOSE_SHARE_DIALOG } from "../utils/actionTypes"; 14 15export function openShareDialog() { 16 return { 17 type: OPEN_SHARE_DIALOG 18 } 19} 20 21export function closeShareDialog() { 22 return { 23 type: CLOSE_SHARE_DIALOG 24 } 25} 26 27 28 29/** 30 * reducers/HeaderShareDialogReducer.js 31 */ 32import * as actionTypes from '../utils/actionTypes' 33 34const initialState = { 35 dialogOpen: false, 36} 37 38export default function HeaderShareDialogReducer(state = initialState, action) { 39 switch (action.type) { 40 case actionTypes.OPEN_SHARE_DIALOG: 41 console.log('dialogOpen: true') 42 return Object.assign({}, state, { 43 dialogOpen: true, 44 }) 45 case actionTypes.CLOSE_SHARE_DIALOG: 46 console.log('dialogOpen: false') 47 return Object.assign({}, state, { 48 dialogOpen: false, 49 }) 50 default: 51 return state 52 } 53} 54 55 56 57/** 58 * containers/HeaderDrawerContainer.js 59 */ 60略… 61ここでconnectしてpropsのバケツリレーをしています。 62 63const mapStateToProps = state => ({ 64 mobileOpen: state.HeaderDrawerReducer.mobileOpen, 65 dialogOpen: state.HeaderShareDialogReducer.dialogOpen 66}) 67 68const mapDispatchToProps = dispatch => ({ 69 handleToggleDrawer: () => dispatch(toggleDrawer()), 70 handleOpenShareDialog: () => dispatch(openShareDialog()), 71 handleCloseShareDialog: () => dispatch(closeShareDialog()) 72}) 73 74export default connect(mapStateToProps, mapDispatchToProps)(HeaderDrawer) 75 76 77 78/** 79 * containers/ShareDialogContainer.js 80 */ 81略… 82const mapDispatchToProps = dispatch => ({ 83 handleOpenNotification: () => dispatch(openNotification()), 84}) 85 86export default connect(mapDispatchToProps)(HeaderShareDialog) 87 88 89 90/** 91 * components/HeaderDrawer.js 92 */ 93略… 94const drawerWidth = 250 // Width for Drawer 95 96const styles = theme => ({ 97  略… 98}) 99 100class HeaderDrawer extends React.Component { 101 render() { 102 const { classes, theme } = this.props 103 104 const drawer = ( 105       略… 106 ) 107 108 return ( 109 <div className={classes.root}> 110 <AppBar className={classes.appBar}> 111 <Toolbar> 112 <IconButton 113 color="inherit" // アイコンの色 114 aria-label="Open drawer" // ラベル付け 115 onClick={() => this.props.handleToggleDrawer()} 116 className={classes.navIconHide} 117 > 118 <MenuIcon /> {/* メニューアイコン */} 119 </IconButton> 120 <Typography variant="h5" color="inherit" className={classes.headerTitle} noWrap> 121 <img src={logo} className={classes.logoIcon} alt="header logo" /> 122 Suggesh 123 </Typography> 124 <IconButton 125 color="inherit" 126 aria-label="Share Suggesh" 127 /******** このあたりです ********/ 128 onClick={() => this.props.handleOpenShareDialog()} 129 > 130 <ShareIcon /> 131                 /******** このあたりです ********/ 132 <HeaderShareDialog 133 dialogOpen={this.props.dialogOpen} 134 handleOpenShareDialog={()=>this.props.handleOpenShareDialog()} 135 handleCloseShareDialog={()=>this.props.handleCloseShareDialog()} 136 /> 137 </IconButton> 138 </Toolbar> 139 </AppBar> 140 <Hidden mdUp> {/* md未満 */} 141 <Drawer 142 variant="temporary" 143 anchor={theme.direction === 'rtl' ? 'right' : 'left'} 144 open={this.props.mobileOpen} 145 onClose={() => this.props.handleToggleDrawer()} 146 classes={{ 147 paper: classes.drawerPaper, 148 }} 149 ModalProps={{ 150 keepMounted: true, // Better open performance on mobile. 151 }} 152 > 153 {drawer} 154 </Drawer> 155 </Hidden> 156 <Hidden smDown implementation="css"> {/* md以上 */} 157 <Drawer 158 variant="permanent" 159 open 160 classes={{ 161 paper: classes.drawerPaper, 162 }} 163 > 164 {drawer} 165 </Drawer> 166 </Hidden> 167 <main className={classes.content}> 168 <div className={classes.toolbar} /> 169 略… 170 </main> 171 </div> 172 ) 173 } 174} 175略… 176 177 178 179/** 180 * components/HeaderShareDialog.js 181 */ 182略… 183 184// SNS用シェアボタン 185import { 186  略… 187} from 'react-share'; 188 189const styles = theme => ({ 190  略… 191); 192 193class HeaderShareDialog extends React.Component { 194 render() { 195 const { classes, theme } = this.props 196 197 const shareUrl = "https://animel.f-arts.work"; 198 const title = "Suggesh"; 199 200 /******** このあたりです ********/ 201 return ( 202 <Dialog 203 open={this.props.dialogOpen} 204 onClose={() => this.props.handleCloseShareDialog()} 205 aria-labelledby="alert-dialog-title" 206 aria-describedby="alert-dialog-description" 207 className={classes.root} 208 > 209 <DialogTitle>Suggesh</DialogTitle> 210 <Divider /> 211 <DialogContent className={classes.snsShareButtonArea}> 212            // 様々なシェアボタン 213 略… 214 </DialogContent> 215 <DialogContent className={classes.snsShareButtonArea}> 216 <CopyToClipboard text={shareUrl} // textの値がコピーされる 217 218 > 219 <Button 220 variant="contained" 221 color="primary" 222 className={classes.copyToCripboardButton} 223 onClick={() => this.props.handleOpenNotification()} 224 > 225 URLをコピー 226 </Button> 227 </CopyToClipboard> 228 </DialogContent> 229 <Divider /> 230 /******** このあたりです ********/ 231 <DialogActions> {/* 「DialogActions」DialogへのActionだと認識 */} 232 <Button onClick={() => this.props.handleCloseShareDialog()} color="primary" autoFocus> {/* 「autoFocus」初マウントでフォーカスするかどうか */} 233 閉じる 234 </Button> 235 </DialogActions> 236 </Dialog> 237 ); 238 } 239} 240 241略… 242 243 244 245/** 246 * App.js 247 */ 248略… 249 250const store = createStore(reducers) 251 252function App() { 253 return ( 254 <Provider store={store}> 255 <CssBaseline> 256 <NotificationContainer /> 257 <HeaderDrawerContainer /> 258 </CssBaseline> 259 </Provider> 260 ); 261} 262 263export default App; 264 265 266/** 267 * index.js 268 */ 269略… 270ReactDOM.render( 271 <App />, 272 document.getElementById('root') 273)

試したこと

console.logで結果を表示しているのですが、
dialogOpenはtrueになり、開けることはできるのですが、
closeするときにfalse->trueのような動きになり、結果的にDialogが閉じない現象が起こっています。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

Yahoo! Japanは検索窓の枠を1ピクセル太くしただけで約5億円の広告収入増を達成した、というニュースが以前話題になりましたが、デザインが再訪問率やコンバージョン率に与える影響はますます大きくなっています。こういった背景から、新しいプロダクトを作る場合にはデザイナーを含めたチームを構成してプロジェクトを進めるべきですが、なんらかの制約でデザイナーを確保できず、デザインを勉強したことのないエンジニアが、UIの優れた成果物をアウトプットしなければいけない状況もあるでしょう。

 Reactではサードパーティーによって開発された、さまざまなコンポーネントがMITライセンスで公開されています。これらを活用することで、ある程度しっかりした作りのアプリを比較的容易に開発できるようになります。利用目的がはっきりと決まっている場合はGitHubに公開されているコンポーネントを利用してもいいですが、ここでは最も有名なコンポーネントセットの一つである、Material-UIを利用する方法を紹介したいと思います。

投稿2020/01/19 17:58

torisetu

総合スコア80

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

こんにちは

動作確認はできないので、実際にうまくいくかは分かりませんが、「ここが怪しいのでは?」と思ったところとその解決策を回答します。

以下の部分

jsx

1<IconButton 2 color="inherit" 3 aria-label="Share Suggesh" 4 onClick={() => this.props.handleOpenShareDialog()} 5> 6 <ShareIcon /> 7 <HeaderShareDialog 8 dialogOpen={this.props.dialogOpen} 9 handleOpenShareDialog={()=>this.props.handleOpenShareDialog()} 10 handleCloseShareDialog={()=>this.props.handleCloseShareDialog()} 11 /> 12</IconButton>

にて、 HeaderShareDialogIconButton の子コンポーネントとして書いていますが、これが原因のように思えました。

ですので、 HeaderShareDialogIconButton で囲まないところ、例えば以下

jsx

1<div className={classes.root}> 2 ・・・ 3 <HeaderShareDialog 4 dialogOpen={this.props.dialogOpen} 5 handleOpenShareDialog={()=>this.props.handleOpenShareDialog()} 6 handleCloseShareDialog={()=>this.props.handleCloseShareDialog()} 7 /> 8</div>

のように、 <div className={classes.root}> 直下の子コンポーネントの最後尾に移動してみるといかがでしょうか?

参考までに、material UI の Dialogのサンプル で、アプリ全体のコンポーネント SimpleDialogDemo は以下

jsx

1 <div> 2 <Typography variant="subtitle1">Selected: {selectedValue}</Typography> 3 <br /> 4 <Button variant="outlined" color="primary" onClick={handleClickOpen}> 5 Open simple dialog 6 </Button> 7 <SimpleDialog selectedValue={selectedValue} open={open} onClose={handleClose} /> 8 </div>

を return していますが、return している JSXの中で SimpleDialogは、 ダイアログを開くボタン Button の子コンポーネントにはなっていないです。

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

投稿2019/09/11 00:59

編集2019/09/11 01:06
jun68ykt

総合スコア9058

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/09/11 02:30

こんにちは???? ご回答ありがとうございます! 実は先程、propsで受け取った関数を変数に代入してから使用したところ無事動作致しました。ですが、いまいち理由がはっきりしていないため、ご指摘頂いた方法も一度試してみようと思います!
jun68ykt

2019/09/11 04:04

どういたしまして。参考になれば幸いです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問