Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Showing Snackbar with React Redux

First off, I'm completely new to React and Redux.

I'm having troubles with showing the Snackbar from material-ui as a notification panel whenever I've dispatched an event.

See mockup code for my example. The notification is not shown at all this way since this.props.sending in App component sets to false immediately when API call is successful.

Now if I skip the SOMETHING_FULFILLED dispatch everything seems to work fine. The state.open of the Notification component is set to false thanks to my onRequestClose function, but since the this.props.sending in my App component is still set to true - then every time the App component re-renders it shows the notification.

Any idea how I would implement this correctly?

I've got a action that looks something like this.

const doSomething = (data) => {
  return dispatch => {
    dispatch({
      type: 'SOMETHING_PENDING',
      payload: { data }
    })

    apiCall.then((complete) => {
      dispatch({
        type: 'SOMETHING_FULFILLED',
        payload: { data }
      })
    })
  }
}

And my reducer looking like this.

const initialState = {
  sending: false
}

const SomeReducer = (state=initialState, action) => {
  switch (action.type) {
    case 'SOMETHING_PENDING': {
      return {
        ...state,
        sending: action.payload
      }
    }

    case 'SOMETHING_FULFILLED': {
      return {
        ...state,
        sending: false
      }
    }

    default: {
      return state
    }
  }
}

export default SomeReducer

My App component connected to the store.

import React, { Component } from 'react'
import { connect } from 'react-redux'

const storeData = (store) => {
  const data = {
    sending: store.Reducer.sending
  }

  return data
}

class App extends Component {
  render() {
    return (
      <Notification sending={this.props.sending} />
    )
  }
}

export default connect(storeData)(App)

And my Notification component.

import React, { Component } from 'react'
import Snackbar from 'material-ui/Snackbar'

class Notification extends Component {
  constructor(props) {
    super(props)
    this.state = { open: false }
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.sending) {
      this.setState({ open: true })
    } else {
      this.setState({ open: false })
    }
  }

  closeNotification = () => {
    this.setState({ open: false })
  }

  render() {
    return (
      <Snackbar
        open={this.state.open}
        message={'test'}
        autoHideDuration={4000}
        onRequestClose={this.closeNotification}
      />
    )
  }
}

export default Notification
like image 884
wannabefounder Avatar asked Oct 17 '22 19:10

wannabefounder


1 Answers

If I'm reading you correctly, it sounds like you have your Snackbar working properly, but it closes too quickly. You'd like it to show but then auto-close itself 4 seconds later, even if the API call itself only took .5 seconds for example. Is that correct? If so, I believe you can simply skip re-rendering your component when the state.open is being changed from true to false (but still allow render when going from false to true):

shouldComponentUpdate(nextProps, nextState) {
  // Only re-render when snackbar is going from closed to open
  return !this.state.open && nextState.open;
}
like image 138
Jeff McCloud Avatar answered Oct 21 '22 00:10

Jeff McCloud