Dispatch a Redux action with the subsequent action as payload to show a snackbar or dialog of Material UI

匿名 (未验证) 提交于 2019-12-03 03:05:02

问题:

I'm using React with Redux and Material UI to build a webapp. The webapp is made of several pages and components. I know that a snackbar or dialog should be directly connected to what the user is doing. However, I'd like to make the snackbar and dialog independent on the pages and components. A use case therefore is displaying a message like background synchronization of your data failed and an action retry now. My idea was to render the snackbar on a page called RootFrame, which is used to wrap all other pages and to dispatch the text of the snackbar as payload of an action.

My Redux action to show a snackbar:

export function showSnackbar(message: string) {   return {     type: SHOW_SNACKBAR,     payload: message   }; } 

Of course it might also be good to specify the message in the action instead of taking the message as argument but that's not my problem right now. The problem is: How can I use this system and display a snackbar with an action? Can I change my action to

export function showSnackbar(message, action) {   return {     type: SHOW_SNACKBAR,     payload: {       message,        action     }   }; } 

and render my snackbar in the RootFrame like

<Snackbar   message={this.props.message}   ref='snackbar'   onDismiss={() => this.props.dispatch(dismissSnackbar())}   action='retry now'   onActionTouchTap={() => this.props.dispatch(this.props.action)} />; 

When the snackbar is dismissed, an action changes a variable in the state: snackbar.visible = false. This is used to activate the snackbar (it is rendered when snackbar.visible === true). When the user clicks on retry now, the action to start the sync (which is passed to the component as props) should be dispatched. The problem is very similar when using dialogs. So not only the text to display but also the next possible actions have to be passed to the component.

Do you think using Redux like this is ok or is there a better solution?

回答1:

Actually, right now usign redux was changed a little bit. We use createAction from redux-act, properly we use createReducer further. In a component we use connect decorator or class from react-redux. Connector provides redux state, dispatched actions, parent props. So for our snackbar we have:

  1. actions:

    export const showMessageTop = createAction(); export const closeMessageTop = createAction(); 
  2. Reducer:

    import {createReducer} from 'redux-act'; import * as ac from '../actionCreators/messageTop'; export default createReducer(   {     [ac.showMessageTop]: (state, messageText) => ({messageText}),     [ac.closeMessageTop]: () => ({messageText: ''}),   },   {     messageText: window.location.search === '?login=1'                ? 'Welcome'                : '',   } ) 
  3. And a component(use decorator instead of class):

    import {closeMessageTop} from '../../actionCreators/messageTop';  import MessageTop from './MessageTop'; @connect(state => ({   // gettext: gettext(state.locale.messages),   messageText: state.messageTop.messageText, })) export default class MessageTopContainer extends React.Component { ... <button onClick={...bindActionCreators({onClose: closeMessageTop}, dispatch)}/> 

So in current props we have this.props.messageText. And we can show this bar if we have message, or we can invoke closeAction which sets up messageText in empty string.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!